How to Store Passwords Securely

I am not a security specialist, but I would have thought that by now, one year after the humiliating hack of Sony Pictures by LulzSec, people would have learned how to handle passwords properly. Apparently NOT.

In the past week, LinkedIn, eHarmony and Last.fm got their password databases hacked and stollen. It’s hard to know how the database was compromised in the first place, but the sheer level of amateurism incompetence that these large companies have demonstrated is shocking.

So, here is how it should be done:

  1. Do not store passwords in plaintext in the database

    • Duh! Well Sony did store a million passwords like that…

    • So did Savannah, a GNU website hosting free software, until they got hacked in December 2010.

    • Users tend to re-use passwords everywhere. So even if your website does not have sensitive data, if it gets hacked, your users might get compromised on other websites such as gmail, Facebook, etc…

  2. Do not use MD5

    • Seriously. MD5 is dead, broken. It should be removed from every library and operating system, as it provides no more security than a CRC. MD5 is too easy to parallelize and too cheap to compute. Relatively inexpensive hardware such as high end GPUs, or FPGAs, make it possible to compute large number of hashes without spending much money nor time.

    • In fact, MD5 is so broken that we have seen a chosen prefix collision attack used in the wild to spoof Windows Update certificates and distribute the Flame malware. (And yeah you guessed it, Microsoft subsequently revoked all its remaining MD5 certificates!)

    • eHarmony and Last.fm both used MD5. But that was also the case of the so-called “experts” of HBGary, that security firm with government contracts, that threatened Anonymous last year and got hacked by them soon afterwards.

  3. Use a Salt

    • Do not just hash the password and store the result into the database. Even if your hash function is better than MD5, it is possible to compute all hashes in advance for common passwords and create a rainbow table. It is trivial to download existing rainbow tables for standard hash functions, and get off-the-shelf tools to use them.

    • Instead you should salt your hashes. A salt is a random piece of data that is somehow combined to the password before it is hashed. Using a salt can be as simple as performing a XOR between the password and the salt, before using the hashing function.

    • Be sure that you use a cryptographically secure random number generator to create the salt, such as Yarrow or Fortuna with a good source of entropy, rather than the built-in rand() function which is only a pseudo random number generator (hence predictable and non-secure). Many operating systems provide this facility via /dev/random.

    • None of the sites hacked last week (LinkedIn, eHarmony and Last.fm) used a salt, nor did the so-called “experts” from HBGary. Some of these password hashes can be downloaded from the PirateBay here and here.

  4. Use more than one salt

    • To make it even harder, it’s best to not re-use the same salt for every password. A good strategy is to create a unique salt for each password and to store it along side the hash in the database.

    • You can also combine this “per-password salt” with a “global salt” that you do not store in the database. This makes is virtually impossible to attack your passwords if only the database was compromised (via a SQL injection for example…)

  5. Use the hash function multiple times (PBKDF2)

    • Cryptographic hashing functions are usually optimized for speed. But in the case of passwords, the amount of data to hash is very small and therefore the hash function runs very quickly. The speed plays to the advantage of the attacker not you. A good way to slow down the computation process is to re-use the same hashing function multiple times.

    • In fact, rather than re-inventing the wheel and taking risks, one can use an off-the-shelf key derivation algorithm such as PBKDF2 or scrypt.

    • For example, Apple uses PBKDF2 with 10,000 iterations on iOS devices.

  6. Probably stay away from SHA-1 too

    • SHA-1 is still considered secure, but it is definitely on the way out. It’s 17 years old after all.

    • You should use the more recent SHA-2 variants (SHA-256, SHA-512, SHA-384) or, if you do not trust the NSA, something like Whirlpool.

Obviously, having a proper password “storage” system in place will not save your website from being hacked. But it will make it more difficult to exploit the password data if that were to happen. You should also test and pay attention to the implementation of the cryptographic functions. Try to re-use well established, peer reviewed implementations that have withstood the test of time.

And as a final note, do not forget to test your authentication system regularly. Recently, a vulnerability was discovered in MySQL that completely broke the authentication for some combinations of compilers and operating system. The bug was caused by a simple “loss of precision” cast from a 4 bytes to 1 byte, which probably trigged a warning in GCC but was ignored for a while. The smallest details matter.