• Anti SteamID 'Spoofing' Measures
    208 replies, posted
[QUOTE=blackops7799;24470091]Probably OP. Also this fix seems to work still. [code]15:47:56 L 08/30/2010 - 14:47:42: "?g&#8224;.??????<1430><STEAM_0:1:25012594><>" disconnected (reason "SteamID validation failed (timeout)")[/code][/QUOTE] It's still not a solution. After some research, it appears that an alternative method of verifying ticket ownership can be used to gain an approval callback whilst using an ID that isn't yours. When a client connects to a game server they generate a 64-bit session ID/token that is located in the application ticket header. This is sent to the Steam backend by the client and is valid as long as the actual owner is in GMod and does not generate a new token by connecting to another server. It seems to be ignored if the client's IP that sent the "I am now playing GMod on server X" matches the one connecting to the game server, but otherwise it compares the token last sent to the backend with the one sent by the client connecting to the game server to check authenticity. In short, if you steal an application ticket and manage to use it before the owner joins somewhere else or closes GMod then you are approved.
Damnnn. :ohdear:
Well... let's wait until it's broken again.
[QUOTE=Ideal-Hosting;24468276]What did I just say? Edit: [b]Just tell your admins to not join servers they don't know?[/b] They can only use SteamIDs from Players that joined their server before.[/QUOTE] he's not a server owner he is one of avasters boyfriends
[QUOTE=Night-Eagle;24468526]If Valve does respond, Valve is probably going to do one of two things: -Make the server return STEAM_ID_PENDING for unvalidated clients[/QUOTE] This is what Steam originally did, and what the point of PlayerAuthed was for, when the backend validated a steam ticket. Alfred promised a fix a week ago, mentioned "clarifying" the nature of the steamid before it was validated, so that's likely what he's going to do, revert it to pending. This would cover everything except the case of using someone's single-use token before they invalidate it. Your solution for ignoring any SteamID checks until PlayerAuth is called is a valid method (you're simply reproducing the STEAM_ID_PENDING except at a higher level).
Just so as everyone knows - you should check if a SteamID is pending in your scripts. It could cause problems if you have a saved points script, money script or whatever.
Token validation appears to work in other Source games too, maybe that will get Valve's attention.
[QUOTE=T3h raps13r;24466935]There [i]is[/i] a new serenity version, and it works 100%.[/QUOTE] Don't tell people that :saddowns:
It's known?
[QUOTE=|FlapJack|;24472537]you should check if a SteamID is pending in your scripts[/QUOTE] What I'm saying is that we need to formally standardize the way we check if a SteamID is pending (if this is the route we are to pursue). If this has already been established, please tell me. I see two simple possibilities: [lua] /* Checks if a player's SteamID has been authenticated */ function playermt:IsSteamAuthenticated() return true // true is a placeholder end [/lua] The second is overriding the IsAdmin() checks to support legacy code. We would deprecate out IsAdmin and replace it with IsAuthAdmin and IsAnyAdmin: [lua] /* Override default IsAdmin and adds authentication check, repeat for IsSuperAdmin */ local oldIsAdmin = playermt.IsAdmin function playermt:IsAdmin() ErrorNoHalt("<player>:IsAdmin() is deprecated. Use <player>:IsAuthAdmin()\n") return self:IsAuthAdmin() end function playermt:IsAuthAdmin() return true and oldIsAdmin(self) // true is a placeholder end function playermt:IsAnyAdmin() return oldIsAdmin(self) end [/lua] That just leaves the problem of identifying unauthenticated players. Take a script that assigns ownership of an entity to a player. We have [lua] self.Owner = pl:SteamID() [/lua] Furthermore, SteamIDs may be written to a file or transmitted in plain-text [lua] file.Write("admin.txt", pl:SteamID()) umsg.Start("hi", pl) umsg.String(pl:SteamID()) umsg.End() [/lua] So, we need to consider the serialization of player identification data. Are we going to use IP addresses? What if a player logs in from a public terminal? What if a player logs in from a different IP address? Should the data expire? Unfortunately, I don't have all the answers and will not claim to, but: For sanity's sake, let's assume that the player is going to stick around long enough to be authenticated. We would need to update all serialized data if we assume instant authentication - perhaps we can avoid this by forbidding serialized data to be used once a player disconnects. This means all unauthenticated serialized data expires as soon as a client is lost (map change/etc). So, players cannot save data to the server until they are authenticated. This is a form of aggressive DRM, however - even if we allow authentication to be supplemented by an IP to SteamID translation table. If we were to pursue this route, however, note that we could make repeat authentications faster by saving a table of IPs to SteamIDs, but, ideally, these must expire after time, and the player must have an option to opt out of this service in case they are using a public terminal. Say, a checkbox in the settings menu to enable the service. Thus, we won't have much of a problem with a lack of data saving for complaintants. I don't like this, though, because its a form of aggressive DRM. However, I have an alternative in mind... [b]NOW THE INTERESTING IDEA:[/b] Perhaps there is an alternative, involving public and private keys. We're not concerned with piracy - that is what the SteamID check is for - we are concerned with instant, gratuitous identification and security. Generate for each client, on every install, a public and private key. On connection, transmit client's public key to server, server generates a random number and encrypts it. The unencrypted number is concatenated to a player's SteamID and stored in a table. The encrypted number is sent to the client and the client remembers it. Salts are used to prevent replay attacks. You should see where I'm going with this. "But what if a client forgets his/her private key?" Easy - they lose all their data on the server. But, they can retrieve it! - the player is generated [i]new[/i] keys and uses those for temporary data (if needed). When they are authenticated, the server can check to see that their authenticated SteamID matches the unauthenticated SteamID given before. Now, here's the important part: we [b][u]PROMPT[/u][/b] the user to make sure that [i]is[/i], indeed, their stash. Who knows, someone might have framed them of a crime and stashed drugs in there. But, here, we are not using SteamIDs as a form of DRM, but a way to retrieve your data if you forgot your password. Think of it like Steam Cloud - pirates aren't invited, and your data is stored elsewhere! We could go crazy and allow the server to save, I don't know, 3 different keys per player. After that, the player could copy his key file to other installations of GMOD. If you have a better idea, I'm all ears. [editline]04:06PM[/editline] I just realized, if we cut out the data retrieval part of this, we could implement this without Valve's assistance. It could be pretty annoying if you lost your key, though. [editline]03:58PM[/editline] [QUOTE=AzuiSleet;24472491]...what the point of PlayerAuthed was for...[/QUOTE] Wait, so does [url=http://wiki.garrysmod.com/?title=Gamemode.PlayerAuthed]PlayerAuthed[/url] mean that the player's SteamID has been "authenticated" correctly? Or do you mean that it no longer works that way?
[QUOTE=Night-Eagle;24474759]We would deprecate out IsAdmin and replace it with IsAuthAdmin and IsAnyAdmin[/QUOTE] That's a really stupid idea. ply:IsAdmin() and ply:IsPotentiallySpoofedAdmin() would work just as well, and wouldn't break every single admin related script.
I laughed.
[QUOTE=Night-Eagle;24466849]It may be prudent to override the IsAdmin() and IsSuperAdmin() functions to return false until authentication is made, or to override them with a separate authentication scheme. Albeit this is a workaround, this is how I would do it on a public server until a patch goes up. [b]Edit:[/b] If this seriously has been going on since June, a supplement to the above fix would be for the server to maintain a list of authenticated IP addresses to SteamIDs. Whenever the Steam backend authentication comes through, the player's SteamID and IP address is added to the table. To allow administrative access [i]before[/i] Steam authentication, this table could be looked up by IsAdmin(). The same table could be used to determine authenticity of repeat-joiners. The only other concern is making sure not to ban a player by SteamID until their SteamID is verified (add an IsSteamAuthenticated() method) - until that authentication, it may be best to rely on IP bans.[/QUOTE] I would go a little further. As covered already, there are edge cases where a faulty approval callback can be issued. Due to the timeframes involved it essentially requires a single person to be targeted. We've known about it for a while but apparently it's public knowledge now. Just another symptom of the underlying problems with the steam backend. For this reason I would instead rely on a password (unique to each user) combined with steamid. You shouldn't be trusting only one factor, no matter how secure you think it is. (Especially since steamids have been shown to be insecure). [QUOTE=Night-Eagle;24468526]If Valve does respond, Valve is probably going to do one of two things: -Expose the validation callback -Make the server return STEAM_ID_PENDING for unvalidated clients They will most likely not have servers wait for validation before accepting a client as this would be seen as an aggressive form of DRM. So, the problem will fall to garry.[/QUOTE] The validation callback is already reasonably easy to access non-invasively with opensteamworks. The big problems right now are that it isn't completely reliable. From one of the responses that we got from valve, STEAM_ID_PENDING sounded most likely and is in my opinion the best solution. PlayerAuthed already exists so scripts [i]should[/i] already be able to handle this delay. For the scripts that can't... well, this is serious enough to warrant breaking existing scripts. [QUOTE=Night-Eagle;24468526]Garry can do a number of things [i]after[/i] Valve takes action: -Do the aggressive DRM thing (blanket solution, much bickering will ensue) -Create some quasi-spectator mode for when players join, disallowing them much access to prevent the problem of identification by unverified SteamID (blanket solution, much bickering will ensue) -Create a new Lua binding ( IsSteamAuthenticated() or whatever ) and publicly announce it; but this leaves a significant period of time where servers are open to attack while a much larger audience is made aware of the security vulnerability (is this still a concern)? So, garry could implement a "blanket fix" once Valve responds...but I can't think of one that won't be intrusive. Thus, [b]the problem falls to the Lua scripters[/b] (user-level). Is there any way it could possibly not? (Not a rhetorical question)[/quote] There is no non-intrusive fix at the game or engine level. I would like to see an engine fix along the lines of STEAM_ID_PENDING (hell, we survived gmod9), but these are all changes that garry is unable to make until the engine is properly secured. You are correct, this is our problem and garry can't really help us (outside of getting valve to fix it). [QUOTE=Night-Eagle;24468526]The only options in this category I can think of is exposing a binding like IsSteamAuthenticated(), or setting STEAM_ID_PENDING...of which, the former is more palatable, as some scripts would probably take STEAM_ID_PENDING as a valid identifier. If we can decide right [i]now[/i] that IsSteamAuthenticated() (or what have you) is the way to go, then we can be ready for the fix on day zero and minimize the added risk of increased publicity (albeit it has been on the forums since June - still, I didn't notice the thread until now; how many more?). So, perhaps a silent update could add a placeholder function. Admin mod writers could implement this function before the fix goes live. Server administrators could override this function with third-party code before the fix goes live. Everyone is happy, and we avoid the administrative "standards" of GMOD 9. In conclusion: if we agree that a user-level solution is the best solution, then the best thing we can do right now is standardize the way we check for authentication.[/QUOTE] This is serious enough that those older scripts need to break. PlayerAuthed exists to keep scripts from using an invalid steamid. Scripts should already be able to cope with this; if they can't, they shouldn't drag the security of the platform down as a whole. [QUOTE=Night-Eagle;24474759]Huge amounts of information[/QUOTE] [b]Legacy stuff:[/b] Well, as far as supporting legacy IsAdmin/IsSuperAdmin stuff goes, rather than waiting for the callback (which isn't currently 100% reliable, just close to it), I'd require the admin to authenticate with a password. It's really the only way to be certain that they are who they say they are. Two (or more) factor authentication is the only solution. [b]Interesting idea:[/b] It's very interesting but I see too many people doing stupid stuff with their private keys, including not realizing how private they need to be kept. The other issue is that they are relatively easy to steal; the source engine has been the victim of a number of arbitrary file reading/writing exploits on both the server and client ends. [b]PlayerAuthed[/b]: This isn't handled by the approve/deny callbacks. As near as I can tell the engine doesn't wait for the backend before firing this off to the game. If they changed it to wait for an approval callback, it would be a huge improvement over the current situation. [b]In a nutshell[/b]: The engine needs to wait until the callback approves a ticket before handing it off to the game (and in turn, Lua), supplying STEAM_ID_PENDING or friends in the mean time. The steam backend itself needs to change the way it deals with the tokens used in apptickets to prevent the faulty approval callbacks from being issued and also ensure that deny callbacks are issued in a decent amount of time. In the event of a lost connection to the steam backend the server needs to catch up with any authtickets that were sent to it when clients connected. Hopefully I've caught up with everything. EDIT: Thinking about it some more, if the engine were to wait for the approval callback before sending a steamid to the game, everything would be fine and dandy and garry wouldn't have to do a thing. No new Lua functions would be required, scripts that use PlayerAuthed like any decent script should will continue to function perfectly, and everybody can go back to forgetting why trusting the steamid alone is a stupid idea. Since the faulty approval callback is now public, the one and only foolproof solution is for a server to require openid identification with the steamcommunity provider and to then lock a steamid to the ip that authenticated with openid. It's a huge pain for people with dynamic IP addresses but it's also guaranteed to work.
[QUOTE=Lexic;24475384]break every single admin related script[/QUOTE] That's kind of the point. The change doesn't have to take place over night, and server admins could opt-in to keep the deprecated functionality if they wished to. The idea is to avoid a mess with scripts that cache a player's admin status, but you're right, a warning might suffice. Like, a warning with blinking neon lights and a klaxon. Given the miniscule risks of keeping it as IsAdmin, though (Oh no, I can't use my banhammer), it's not [i]that[/i] critical.
I just finished writing and testing a Python implementation of this exploit, and wondering whether I should release it freely under the GPL.
[QUOTE=Night-Eagle;24475635]That's kind of the point. The change doesn't have to take place over night, and server admins could opt-in to keep the deprecated functionality if they wished to. The idea is to avoid a mess with scripts that cache a player's admin status, but you're right, a warning might suffice. Like, a warning with blinking neon lights and a klaxon. Given the miniscule risks of keeping it as IsAdmin, though (Oh no, I can't use my banhammer), it's not [i]that[/i] critical.[/QUOTE] Why don't you simply ramp IsAdmin up to the new beefy stage and have IsPotentiallySpoofedAdmin using the old method for anyone that feels like using it? If your method was ever implemented, I wouldn't go through my scripts to update them, I'd just go _R.Player.IsAdmin = _R.Player.IsAuthAdmin in an autorun file and forget about it, as would most other people. Why go through the bother? :/ [editline]12:25AM[/editline] Except the people that don't understand, and then start to complain about all the spam in their console, because they use old scripts that still work but aren't maintained.
[QUOTE=q3k;24475678]I just finished writing and testing a Python implementation of this exploit, and wondering whether I should release it freely under the GPL.[/QUOTE] That would make Avaster angry. He can't sell serenity then...
[QUOTE=q3k;24475678]I just finished writing and testing a Python implementation of this exploit, and wondering whether I should release it freely under the GPL.[/QUOTE] If you do go the public disclosure route, valve won't take any action unless it affects them. If you really care about getting it fixed, don't target garrysmod. They've ignored it with garrysmod for eight months now. If this tool were to be released people using cracked games would be able to play multiplayer on legitimate (but VAC insecure) servers. Valve doesn't care about the security problems for us or the piracy problems for garry, but they sure as hell will care about piracy problems for themselves. That said, I'm generally against this being made public. In the time that it takes valve to fix it it's really unfair to a lot of people; server hosts and the people who find their steamids stolen alike. If we complain about this problem publicly enough they'll probably come around on their own--I don't want to have to enable piracy in order to get this fixed.
[QUOTE=Ideal-Hosting;24475956]That would make Avaster angry. He can't sell serenity then...[/QUOTE] Isn't Tranquility freely available at the moment anyway?
[QUOTE=Ideal-Hosting;24475956]That would make Avaster angry. He can't sell serenity then...[/QUOTE] who cares
[QUOTE=Night-Eagle;24475635]That's kind of the point. The change doesn't have to take place over night, and server admins could opt-in to keep the deprecated functionality if they wished to. The idea is to avoid a mess with scripts that cache a player's admin status, but you're right, a warning might suffice. Like, a warning with blinking neon lights and a klaxon. Given the miniscule risks of keeping it as IsAdmin, though (Oh no, I can't use my banhammer), it's not [i]that[/i] critical.[/QUOTE] Is there any reason you prefer additional functions to PlayerAuthed simply being called later? It's easier to update poorly coded scripts, works fine with properly coded existing scripts, and doesn't even require an update on garry's part.
[QUOTE=Lexic;24476052]Isn't Tranquility freely available at the moment anyway?[/QUOTE] Nope. He is only selling Serenity 2.5 ;) I have a screenshot of it.
[QUOTE=ComWalk;24476090]Is there any reason you prefer additional functions to PlayerAuthed simply being called later? It's easier to update poorly coded scripts, works fine with properly coded existing scripts, and doesn't even require an update on garry's part.[/QUOTE] Because that wouldn't rock the boat enough.
[QUOTE=Lexic;24476052]Isn't Tranquility freely available at the moment anyway?[/QUOTE] Public Tranquility is broken and the private version is just used for testing purposes.
[QUOTE=ComWalk;24476033]If you do go the public disclosure route, valve won't take any action unless it affects them. If you really care about getting it fixed, don't target garrysmod. They've ignored it with garrysmod for eight months now. If this tool were to be released people using cracked games would be able to play multiplayer on legitimate (but VAC insecure) servers. Valve doesn't care about the security problems for us or the piracy problems for garry, but they sure as hell will care about piracy problems for themselves. That said, I'm generally against this being made public. In the time that it takes valve to fix it it's really unfair to a lot of people; server hosts and the people who find their steamids stolen alike. If we complain about this problem publicly enough they'll probably come around on their own--I don't want to have to enable piracy in order to get this fixed.[/QUOTE] You are absolutely right. But wouldn't it be better if the exploit was available to everyone, and not just a couple of skiddies who paid for it?
[QUOTE=ComWalk;24475628][b]Interesting idea:[/b] It's very interesting but I see too many people doing stupid stuff with their private keys, including not realizing how private they need to be kept. The other issue is that they are relatively easy to steal; the source engine has been the victim of a number of arbitrary file reading/writing exploits on both the server and client ends.[/QUOTE] Perhaps if we call it "password_key_do_not_share" instead of "key", we could avoid the first problem. About the arbitrary file reading/writing exploits: Valve can fix those once they catch them, right? Valve can't really fix this problem with instant/offline identification. Also, is it not possible for a program to open a particular file for exclusive read access while it is running? Finally, the identities that we are creating with public/private keys are disposable assuming that Steam's backend doesn't report wrong information - it just needs to report correct information, or no information at all.
I would say make it public and then everyone open a support ticket about the issue. They must react.
[QUOTE=q3k;24476174]You are absolutely right. But wouldn't it be better if the exploit was available to everyone, and not just a couple of skiddies who paid for it?[/QUOTE] Like I've said before, it's a pretty terrible situation. Would this get it fixed faster? Probably. Would it be worth it? I'm not so sure. I know that we've elected to not publicly disclose it ourselves (but, as I'm sure you've found out, it's not remarkably hard to do from scratch, especially with all the information supplied in this thread), but at the end of the day it's your call. I would really prefer to see if we can get some sort of official response from valve through garry before any kind of drastic action like this was taken.
[QUOTE=Lexic;24475830]Why don't you simply ramp IsAdmin up to the new beefy stage and have IsPotentiallySpoofedAdmin using the old method for anyone that feels like using it?.[/QUOTE] ...that was basically what I said when I replied to you.
[QUOTE=q3k;24476174]You are absolutely right. But wouldn't it be better if the exploit was available to everyone, and not just a couple of skiddies who paid for it?[/QUOTE] But generally speaking, the only people who are going to use it are skiddies and pirates. It's better that only the few skiddies who can pay use it, rather than any skiddie who compiles your code, no?
Sorry, you need to Log In to post a reply to this thread.