I’m going to get on a programming soapbox real quick and cover a topic that seems to confuse some people.
Hashes Are Not *$&%@! Magic
Some people seem to think that swapping out a secret with a hashed version of that secret makes it all safe and cozy, but that’s simply not true.
Yes, cryptographic hashes are a very important part of digital security, for a number of good reasons, but they have to be applied in a manner which takes the whole system into account.
The impetus for this work was a login integration I recently updated, because some other developer foolishly applied hashes.
Essentially, we were cross-posting a login form on one website to another. Nothing fancy. Ignore the lack of CSRF control.
<form method="POST" action="http://theotherguys.saas/login">
<input type="text" name="user" />
<input type="text" name="password" />
<button type="submit">Log In</button>
The New Form
But the new form would need a change. Instead of sending the username and password, we would send the username, and an MD5 hash of the concatenation of username and password.
Now, I’m sure when this idea was implemented, it was sold as a way to authenticate the user, without exposing their password in plaintext (note that they don’t use SSL). Brilliant!
Yes, it does obscure the plaintext password, but it is not any more secure.
You see, they didn’t think about the system as a whole, they were just focused on obscuring the password.
All that happened here is a substitution of shared secrets.
Previously the server compared the username and password it has on file to what was sent in. Now it compares the username and the hashed password to what it has on file. Do you see what we did? We’ve simply swapped the secret of the plaintext password for the secret of the hashed password. I can still intercept your form submission over the wire and steal your credentials.
I don’t have to prove I know the password, I have to prove I know the secret.
Zero gain, and you’ve added complexity.
But MD5 is weak. And we have the salt, if you can call it that, in the username. An old 2Ghz P4 can try about 20 Million hashes a second, and throwing a modern GPU at it you can test several billion hashes a second. If we want the plaintext password, we can get it unless it is reasonably large (7+ characters) and fairly complex (at least one non-alphanumeric character).
For an extra thought, consider how they must be storing these passwords. Either there scheme has always been MD5(CONCAT(username,password)) or they are storing them in plaintext and are (hopefully) migrating to hashed.