Store passwords the right way in your application

Published: 2013-06-11
Last Updated: 2013-06-11 21:59:10 UTC
by Swa Frantzen (Version: 1)
14 comment(s)
I suspect most of our readers know this, but it can't hurt to repeat this every so often as there is a lot of confusion on the issue. One thing that gets to me is seeing reports of website compromises that claim "the passwords were hashed with SHA-256". Well at face value that means 90% of the passwords were decoded before the news hit.
 
If you have an application that's protected by passwords, there are a few rules to follow:
 
Rule #1: Never store plain passwords, use a hash
 
The worst case solution is that passwords are stored as is. Any attacker breaking in to the application now has everything they need to impersonate any user in your application. But typically they have much more: your users typically reuse passwords, so there's no telling to how far this goes. And if the application is e.g. a webmail solution: well all accounts that can be reset by sending an email here are now essentially broken as well.
 
A hash function is a one-way function: it converts input to output but there is no easy way to reverse the process. There's a whole bunch of algorithms commonly used.
 
The goal/advantage here is that even if the attacker takes away the user tables, he's still got some work to do. 
Unfortunately the work is doable so we need more ...
 
Rule #2: Use a salt
 
Attackers can pre-compute (or buy) so called rainbow tables: it's a list of pre-computed password -> hash values and as such decoding any common password is as fast as a lookup to them gets.
 
A salt is essentially a random string chosen at the time of password change or creation and stored along with the hash and concatenated to the password. This makes rainbow tables useless.
 
But it's still not enough...
 
Rule #3: Use a slow hash function
 
This rule is most often forgotten, yet it is so critical. 
 
The most common hash functions we use daily (e.g. SHA-256) are designed to be fast. But for storing passwords that's going to work against us big time.
Even the attacker can't break SHA-512 in a brute force fashion, even if they can't use rainbow tables due to salts being used, they still will find the vast majority of the passwords our users can remember in a manner of minutes to hours if you use a fast hash.
 
So you need to use a slow hash function.
 
Since there's a Rule #0 in all things crypto: Don't invent your own: Just use the appropriate functions already there. Many of these slow hash functions allow one to chose the cost. If so, set it as high as you can bear with your current hardware.
 
Examples
 
In PHP one can use the crypt function using blowfish or many thousands of rounds of SHA-256 or SHA-512 instead of a simple hash function.
Or even better if the cryptographic password hashing extension is installed, use it as it has simple support for e.g. rehashing passwords to update the strength of a hash of a stored password upon login of the user.
 
Feel free to add comments on how to do it in other languages.

--
Swa Frantzen -- Section 66

Keywords: hash password
14 comment(s)

Comments

I store them using notepad as passwords.txt on the desktop. No joke. It works.
Make sure you use ROT26 encryption at a minimum, Alibert.
There's a great write-up on this subject for PHP devs at:

http://www.openwall.com/articles/PHP-Users-Passwords

It includes code examples and links to a small framework that can be used to implement decent password handling without the (relatively-new) password hashing extension.

The article covers additional concerns beyond those listed here, such as timing attacks, input filtering and proper database access.
PBKDF2 is the only FIPS / NIST compliant "slow" hash to use. BCrypt and SCrypt, while nice, will not get you in compliance with a handful of regulations / certifications.
When thinking slow algorithm, make sure it is not slow enough that a hacker can use it for DoS on the server. Put in some logic to prevent they bad guys from doing brute force (.i.e. max 5 attemps per x minutes).
I don't really get the hype around salts.. You have to store the salt somewhere along the user data, or at least something from which the salt can be derived. If the attacker has gotten hold of your user database, he has the hash and the salt, and - in the worst case - even the stored DB procedure for the calculation. Even if he doesn't get the later part, trying out whether the hash fits for a concatenation of a plainly stored salt and password, or trying the usual other combinations (xor unhashed string with registration date etc..) just costs the attacker a few hours more.
@visi:

A salt really is no hype. without a salt the hacker can precompute all passwords he likes e.g. SHA-256("password") = 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8 now with a table of all somewhat likely passwords the attacker has a simple sorted tree where he can look up the hash he found and retrieve the password without computing anything. We call that lookup table a rainbow table.
A salt prevents this attack as the passwords aren't hashed "naked".

The proper way is to generate a random salt per user and store it along the hashed password. In fact the output of the referenced PHP crypt function prepends the algorithm used (optionally the number of rounds used) and the salt to the hash it outputs, so you just store one string.

This way you force the attacker to compute hashes not just for your user table, but also for each and every individual user. A salt is hence all about forcing attackers to compute as many as possible hashes in order to retrieve your user's passwords.
The idea of 're-hashing' to change to a stronger hash on next login never occurred to me before, but sounds great.
I don't understand why more systems don't use a salted "slow" hash with the User ID as well and then include that User ID into the hashing of the password. This has the benefit that a stolen user database doesn't directly reveal User IDs which are often email addresses... which means they're likely to be long enough to be difficult to brute force quickly.
@visi the concept Swa is discussing is called "rainbow tables"
The wikipedia article has a good discussion.
Yes, it doesn't cover a slow a singular brute force, but it dramatically increases multiple account security.
Salting also prevents same password = same hash observations.
- I like the UserId hash idea!

Diary Archives