from Hacker News

Steam's login method is kinda interesting

by zertrin on 1/11/21, 3:27 PM with 226 comments

  • by sroussey on 1/11/21, 7:05 PM

    I mentioned this on Twitter[1], the reason to encrypt before sending over SSL is not about double encryption, it’s about how a large backend system is designed.

    Often, you have load balancers that are SSL endpoints, so the data is decrypted at that point.

    You can start to see the problem already. What if there is a different bug, and so a dev starts logging requests somewhere down the line? You accidentally start logging cleartext passwords. Oops. Facebook was fined for this not that long ago.

    But if the password is encrypted, then it’s not really an issue, and the black box blob can be forwarded to a login microservice. There, the team decrypting will be on higher alert.

    So depending on the structure of various teams, you now have fewer teams that need that kind of security oversight and can move faster.

    Smaller blast radius of something goes wrong.

    [1] https://twitter.com/sroussey/status/1347688753221931010?s=21

  • by Cthulhu_ on 1/11/21, 3:59 PM

    I've heard about the security of a mobile banking app about eight or so years ago, when mobile banking was still very much a new thing and trust was a big issue. They too opted to write a second encryption layer on top of TLS / SSL, fearing MITM attacks. That was also when iOS didn't support SSL pinning yet.

    It seemed to work for them, security researchers went to town on it and while they quickly discovered there was a second encryption layer below SSL, they were unable to determine what it was and how to crack it.

    IIRC their encryption was never broken, and thanks to that track record, they slowly increased daily spend limits over the mobile app.

    Long term, because they were very forward-thinking and they had competent native app developers (as opposed to the competition who struggled for years with mobile web / crossplatform tech), they increased their market share by a lot, now being the largest bank in NL; can't find historical data, but they went from 37% in 2016 to 40% in 2018.

  • by aasasd on 1/11/21, 4:34 PM

    I keep being somewhat baffled by Steam's login process every time I'm forced to go through it. Apparently Steam is such a cesspool of (pre)pubescent teenagers, with rampant account hacking and theft of funds, swag or whatever, that they feel the need to fortify the process if only to make it more inconvenient for the hackers.

    - “Remember the password” barely ever works, even on desktop. Since I don't quite log in every day due to being too old for that, I have to redo the process every time—on a machine that I bought with my own money just for myself and intend to protect with both technical means and physical force.

    - Somehow copy-pasting passwords from KeepassX/XC doesn't work on Mac, with the shortcut. Not sure if this is a misfeature of Steam, but I have to paste the password to an editor first and then copy out of there into Steam. (Seems though that ‘paste’ in the context menu does work—this might've changed since I first noticed the issue.)

    - And of course, the weird variation on 2fa, via email, instead of the good regular TOTP. As is tradition by now, I'm also given the choice of installing yet another app on the phone, which somehow doesn't quite seem to serve my interest.

  • by madisp on 1/11/21, 4:46 PM

    The 3600 second + a bit (~1s) is a common thing that happens if your periodic scheduling work is one-shot and repeating is achieved through scheduling the task again after completion. E.g. consider the following code (in Kotlin, but hopefully still readable):

      fun rotateKeys() {
        publishNewKey(key = generateKey(), timestamp = now())
        schedule(::rotateKeys, 1, TimeUnit.HOUR)
      }
    
    if `generateKey` and `publishNewKey` take around ~1s then you'll observe exactly this behaviour - the timestamps will start drifting from some original value.
  • by noobquestion81 on 1/11/21, 3:47 PM

    If you are wondering why they do this, the answer is not because they don’t trust TLS.

    It is (likely) because they use geographically distributed terminating load balancers, perhaps owned by someone else or run in someone else’s POP, and are trying to prevent passive collection of passwords.

  • by simongr3dal on 1/11/21, 4:26 PM

    I’m just annoyed that Steam still doesn’t support standard TOTP two factor but uses either an email code or their app.
  • by RexM on 1/11/21, 3:58 PM

    World of Warcraft also uses SRP for logging in via the game client. Or at least they did when it was originally released, I don't know if that's still the case.
  • by bArray on 1/11/21, 4:37 PM

    One reason not to trust TLS is that it's one system that you want to be secure for all your users - indefinitely. If in the future there was some method to crack the TLS or the appropriate keys/certs were leaked, any recorded traffic could be retroactively cracked.

    Remember also it wasn't so long ago we were talking about things such as POODLE attacks. For all we know, some bad implementation of TLS 1.3 could default to some crappy easy to crack algorithm.

    I believe there was a paper (can't find it now) that speculated about the cost to crack a specific TLS setup to be about $10 million USD in processing, going back some years. (I think it was in reference to some half of VPN traffic at the time using the same keys.) If Moore's law still applies in any sense, that cost likely halves every two years and people only really change their passwords if they have to.

    Another reason is that it reduces risk server side if you are never handling user passwords - at worst an attacker gets a temporary hash that's valid for a short time, specific to that server. Maybe they can do some harm during that time, but you can ultimately revoke that key and undo the changes to the user's accounts.

  • by superkuh on 1/11/21, 5:25 PM

    It's not listed anywhere on his site but by random guessing of URLs I found his RSS feed: https://owlspace.xyz/index.xml
  • by throwaway09223 on 1/11/21, 6:29 PM

    Not transmitting the password is good practice for the same reason it's good practice to not store passwords cleartext: systems can be compromised.

    I trust we all agree that storing cleartext passwords in a database and doing a simple string compare is a problem so I won't rehash that bit.

    If a login server is compromised then attackers can harvest cleartext passwords. It's the same class of problem with a reduced attack surface.

    There is no good reason to transmit a persistent authentication secret as part of authentication. Just don't do it.

  • by netsharc on 1/11/21, 4:05 PM

    Yahoo! Mail also does (maybe "did", I looked at it a decade ago) something similar. When the user opens the login page, s/he gets a random string in one of the hidden form fields, IIRC it hashes the user-entered password, and then adds the random string and hashes it again, and sends this result to the backend.

    On the backend, it knows the random string it sent to the user, and it has the hashed password in its DB, so it can do the same algorithm and compare the results.

  • by yuliyp on 1/11/21, 6:33 PM

    Regarding the rotation timestamps: My guess is that the rotation is implemented as a "generate a new key when needed" rather than a cron: When someone asks for a key to issue to a user trying to log in, try to fetch a cached one. If one is there and it's < 1 hour old, return it. Otherwise generate a new one and record its timestamp.
  • by simias on 1/11/21, 10:51 PM

    Seems awfully complicated, slow and error-prone to use full blown RSA for this. Why not send a challenge token and hashing salt and ask the user to reply with the (effectively one type password) crypto_hash(crypto_hash(salt, password) + token)?

    On the backend they already have crypto_hash(salt, password), they know the token they sent so they can build the same hash and see if it matches. This way the backend actually never has access to the non-hashed password.

    The only inconvenient I can see is that you can't transparently rehash on login on the backend if you decide to migrate to a different, potentially stronger hash algorithm later. But then again if the worry is that passwords could leak in the backend, using hashes makes it effectively impossible by construction.

    I guess nobody gets fired for using RSA. But at the same time doing "serious" crypto in JS always feels icky to me.

  • by mxscho on 1/11/21, 8:08 PM

    Steam and especially CS:GO has a problem with phishing sites (with fake Steam OpenID pages) where attackers (after getting access to the Steam accounts) can automatically create permanent access to accounts by generating API keys to control those phished accounts.

    This is used e.g. to swap trade offers in realtime, i.e., a trade offer with the actual account is replaced by a trade offer with a bot with a similar looking profile (all set up automatically). All of this is done in the timeframe between the user setting up the trade offer and the actual 2FA mobile confirmation of this trade.

    People are being phished like this for years and Valve fails to take the responsibility to implement a simple anti automation measure at the part of API key generation (e.g. email confirmation or captcha).

    The monetary damage done to users is probably in the high thousands, if not millions, at this point in time.

  • by cafed00d on 1/11/21, 7:54 PM

    It's stuff like this that makes me wish for a _version_ of Windows that is completely built & operated by Valve. Or atleast, I wish Microsoft could implement such features for their login interface.

    I love gaming on Windows & PC and would love to have the PC have a "Big Picture mode" friendly UI, _throughout_ the OS. Some gimmicks I have had to resort to are to set up my PC Sign-In to be _without_ a password and on a _local account_ on my Win10 PC, along with having Steam start in BigPicture on startup. This way I can switch on my PC and have my controller connect to start gaming just like a console; but way better graphics of course :)

    It's these tiny affordances that collectively add up to great User Experience features.

  • by jzer0cool on 1/12/21, 5:46 AM

    I always had some concerns with desktop apps / mobile apps. Unlike browsers which has a lock symbol how can desktop apps inform whether communication is over tls for example? There is also the challenge that it 'was' tls at one point when you first inspected but could later changed to some non secure transmission without being informed of such change.

    What might be some solutions to this? I have yet to see anything that is standardized for this purpose. Other than, loosely here, 2fa token for purpose for login only, but is still without knowing whether transmission to endpoint was over secure channels.

  • by sroussey on 1/11/21, 6:53 PM

    Repeat from a couple days ago: https://news.ycombinator.com/item?id=25690995
  • by apatheticonion on 1/12/21, 12:16 AM

    How hard it is to move to using OIDC with commonly implemented features such as SSO, anomaly detection, passwordless login, app based MFA, etc?

    It's good enough for major financial institutions and available as a service using any number of providers (like Okta, AWS Cognito, Auth0).

    I love Valve and Steam but their game launcher client (Steam) lives in the stone age when it comes to use of technologies.

    That said, it's far better than the competition so I am still happy, but it is still annoying.

  • by warpech on 1/11/21, 11:03 PM

    From the OP

    > the login page also sources jQuery version 1.8.3 which was released in November 2012

    Wow, that's a prime example of "if it works, don't change it"

  • by syoc on 1/11/21, 4:53 PM

    There was some discussion on /r/netsec where this was published as well. https://www.reddit.com/r/netsec/comments/ksn6rc/steams_login...
  • by RupertWiser on 1/11/21, 10:57 PM

    I kept reading waiting for the author to address man in the middle attacks but no mention. This adds no additional security. You can easily provide your own keys or JavaScript and completely bypass this.

    Like others have suggested, I get the impression this system is assuming TLS will work and perhaps isn’t trusting the server the password ends up on.

  • by gitgud on 1/12/21, 6:07 AM

    Not sure if anyone noticed, but according to the "login.js" snippet, Steam removes all non-standard ascii characters from the password, before encrypting it...

    Doesn't that essentially reduce the password's strength? Especially if there's a lot of non-ascii characters in it....

  • by mschuster91 on 1/11/21, 4:40 PM

    > That begs the question why. Why bother creating such a weirdly intricate system on top of something that works just fine on its own? I have my own theory, but keep in mind it’s just that.

    To avoid admins (or hackers) in enterprise "SSL breaker" boxes from exfiltrating passwords.

  • by MayeulC on 1/11/21, 5:53 PM

    If you want fancy password-based authentication without transmitting it, have a look at PAKE (and OPAQUE): https://news.ycombinator.com/item?id=18259393
  • by txr on 1/11/21, 4:41 PM

    This exact procedure is used for the pidgin plugin: https://github.com/EionRobb/pidgin-opensteamworks
  • by rvr_ on 1/11/21, 10:29 PM

    Steam was always a high target for hackers and a low target for law enforcement (who cares about your stolen games?). It makes a lot of sense for them to implement every security method conceivable.
  • by spondyl on 1/12/21, 1:51 AM

    On a side note, I'd like to say I'm a big fan of this blog theme the author has going.

    It has a kind of homey feel thanks to the owl and the little + symbols in the background wallpaper

  • by g7r on 1/12/21, 3:41 AM

    This strange solution looks like a legacy of times when Steam used HTTP instead of HTTPS. Maybe they just didn't bother to update working code after migration to HTTPS?
  • by bullen on 1/12/21, 4:29 AM

    I use single serving server salt and SHA256 hashing for my logins: http://talk.binarytask.com
  • by nirushiv on 1/11/21, 6:53 PM

    How does this work implementation wise? One private key per application? Per user? Or refreshed on a per-login basis on the first POST?
  • by BlueTemplar on 1/11/21, 5:25 PM

    I wonder what did they use between 2003 and 2012 ?
  • by hamilyon2 on 1/12/21, 12:23 PM

    I always wondered what would HN say in this case. Clearly, steam is rolling its own crypto here, against established practice.
  • by ezconnect on 1/12/21, 6:35 AM

    This is done by bank login page during the 2000s and still being done by my bank and other bank login page.
  • by bricss on 1/11/21, 8:59 PM

    It seems to me that whoever wrote this article has no idea what an MITM attack means.
  • by qorrect on 1/11/21, 4:53 PM

    > The internet was a different place though in the early 2010s

    Oh how far we've come. /s

  • by deepsun on 1/11/21, 10:59 PM

    tl;dr:

    User client requests a public key from Steam's servers (rotated each hour), and sends passwords encrypted with it.

  • by jordache on 1/11/21, 6:14 PM

    This is clearly a violation of security good practice tenet of not implementing novel patterns.