3

I've been investigating various protocols used to send usernames and passwords to web servers in order to authenticate, and while obviously all of them these days use SSL/TLS, I was a bit surprised to see that even with my online banking sites the passwords are literally included "as is" in the form body with no attempt to hash or otherwise protect them. Meaning that if either a) somebody has compromised my machine, installing new TLS root authority certificates and causing requests to my online bank to be sent to another server or b) has managed to direct me to a site looking so convincingly like my online banking site that I don't notice it's not (e.g. IDN homograph attack), they can readily capture my online banking password. I could even include c) a malicious operator with access to the backend servers would likewise be able to obtain my password.

The now-popular OAuth 2.0 protocol likewise includes the password unhashed or unprotected as a form field or query parameter (query parameter's arguably even worse as it's not uncommon for query strings to be logged in full by web servers). Given there are well-known and establish protocols for hashing and protecting passwords (e.g. Digest Authentication) that would seem to be provide some obvious benefits in keeping passwords protected, why does it seem to be that nobody is using them?

Even performing a basic SHA256 on the password + pre-determined salt (on the client side) would be better than nothing - obviously if the hash is compromised, an attacker could still use it to access protected services, but at least they don't have any information about my password that could be useful to determine my other passwords, including whatever password I replace the current one with when I'm required to change it (we all know what the most common routine is there!)

The only rationale I can see for passing passwords unprotected (other than over TLS) is that it allows backends to perform complexity validation on them. But even then, that password only needs to be passed once when you first establish it, not for every time you log in (further, the backend could just perform checks against just the hash - e.g. checking against well-known hashes, previously used ones etc., and leave the rest to the client-side, accepting that client-side validations can be bypassed, and it does concern me that even length validation is not something you can do with just the hash).

  • We already have a lot of questions here about possible benefits of client side hashing, e.g. [this](https://security.stackexchange.com/questions/100957/hashing-user-passwords-via-javascript-client-side-versus-server-side-hashing) and [this](https://security.stackexchange.com/questions/8596/https-security-should-password-be-hashed-server-side-or-client-side). In its current form, your question seems pretty much covered there. If there is a particular aspect you don't see explained on SecSE, you can always ask a new question and emphasize that aspect. – Arminius Nov 08 '17 at 19:58
  • it seems like it makes sense, but if you look at actual threat scenarios, it doesn't protect against much. – dandavis Nov 08 '17 at 21:26

2 Answers2

5

Your question boils down to

why do passwords get sent in clear text over an encrypted channel and are not hashed on the client before submission?

The answer is: if the client is compromised to compromise the TLS session, it does not matter - the password is typed in and can be keylogged.

Additionally, hashing on the client side just makes the hash value effectively your new password being send - again - in clear text over the encrypted connection.

Tobi Nary
  • 14,302
  • 8
  • 43
  • 58
  • Yes, that's certainly true for cases where the site is a phishing site - as you suggest, it could be a site that looks like the genuine site, but in fact simply transmits the password in cleartext to the server (then shows some sort of error). So it's really only cases where after the TLS encryption termination the password is not adequately protected (e.g. because it's logged) that client-side hashing would help. – Dylan Nicholson Nov 08 '17 at 21:56
  • Not even then; an attacker in possession of the hash can just send the hash to the regular site, just like the password. The legitimate site can not tell the difference and if the hash is recent, unless you use the time as a salt but that brings you in clock skew hell. – Tobi Nary Nov 09 '17 at 04:26
  • Sure, if your sole concern is obtaining access to that particular site using the current password. But when the user has to change that password (e.g because the attack is detected), an attacker with the previous plaintext password has at least something to go in in terms of guessing the new password, whereas with the just the hash password the attacker nothing that could be used for guessing future passwords (or passwords to other sites). – Dylan Nicholson Nov 09 '17 at 07:49
  • That is usually not how password guessing works. – Tobi Nary Nov 09 '17 at 08:38
3

Crackstation explains it pretty well. Sending the hash over the wire means that the server is validating the hash with the hash it has stored - the hash effectively becomes the users password.

If the server is compromised and the hashes are obtained, they don't need to be cracked to be able to log in as other users.

The correct way to do it is to hash the password on the server and validate it from there.

Joe
  • 2,734
  • 2
  • 12
  • 22
  • I'll have a read of that, but yes I understand about the "hash becoming the password" problem, which is why digest authentication requires the server to store the password hashed against fixed data (username/realm) and then for the client to hash against that AND a nonce (which the server also knows), meaning that effectively the hash of "username+password+realm" becomes your password, but as I mentioned, there's the additional consideration that being able to access a user's plaintext password provides potential additional information about what that user's other/future passwords may be. – Dylan Nicholson Nov 08 '17 at 21:49