Many developers store passwords wrong. Are you one of them? Likely, you’ve stored them in a vulnerable way in the past and maybe you still are. If your company doesn’t have a standard pattern for storing user passwords, or if it does and the pattern doesn’t contain the words “Salt” and “Hash”, this blog post is for you.
When writing user passwords to a datastore, never store them in plain text. If your datastore’s security is compromised, an attacker can easily steal user login credentials, unleashing a major PR incident on your watch. Don’t worry, it isn’t much effort to plan ahead and only incur a minor PR incident, none of which is your fault.
Is there a better way to store passwords than plain text?
Yes! Instead of storing the actual password text, store a hash of that password. Use a strong hashing algorithm like SHA256 or SHA512 to hash the password text and store the result of that. When a user needs to be authenticated, hash the submitted password and compare the two hashes. If they are the same, the password is correct. Unfortunately, hashing alone is not all that much more secure due to something called a rainbow table. Rainbow tables are very large sets of hashed passwords that can be used to convert hashes back to plain text passwords. These tables are readily available through BitTorrent.
Is there a better way to store passwords than using hashes?
Yes! Instead of storing the hash of the password, store a hash of a salted password. A salt is a random string (and unique to each password in your system) that you will append to the password before hashing it. And get this, you’ll store that salt in your datastore in plain text in the column right next to the hash!
What? Are you out of your mind?!
No! It turns out that even if the attacker has the salt and the hash, it doesn’t do them any good. Remember that storing plain hashes isn’t good because of precomputed rainbow tables. These tables are computed off of a large set of text passwords, not passwords with salts on them. The attacker would have to regenerate the tables using the salt from your database and since the salt is unique to each password, generating a different table for each password would take too much time to be a viable option. So using long unique salts is important. Something in the neighborhood of 128 chars should do it. The salts should be random and you should use a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG) to generate them.
Why can’t I write my own hash algorithm?
So the attacker doesn’t know what it is and they can’t create a rainbow table for it, right? This is called security through obscurity and it is a very bad idea. Unless you’re a cryptographer and can prove that your algorithm is a secure cryptographic hash function, don’t go this route. Once the hashing function is reverse engineered, plain text passwords can be computed from the hashes. A rainbow table isn’t even required if the passwords fall out of the hashes if you shake them a little bit.
I forgot my password on site X and they sent it to me in an email. How does that work?
Well, they are storing your password in their system and it is vulnerable. Not to mention that they sent your password over the wire in an email that isn’t necessarily encrypted. Stop using that site and delete your account. Then email the site admin and have them read this blog. A coworker of mine ran into this very thing a couple weeks ago on a major home services provider site. This is still a real problem so spread the word and educate your fellow developers.