Store passwords the right way in your application
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.
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
×
Diary Archives
Comments
alibert
Jun 11th 2013
1 decade ago
dsh
Jun 11th 2013
1 decade ago
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.
Patrick W. Barnes
Jun 11th 2013
1 decade ago
hackajar
Jun 12th 2013
1 decade ago
PHP
Jun 12th 2013
1 decade ago
Visi
Jun 12th 2013
1 decade ago
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.
Swa
Jun 12th 2013
1 decade ago
Steven Chamberlain
Jun 12th 2013
1 decade ago
PHolder
Jun 12th 2013
1 decade ago
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!
davem
Jun 12th 2013
1 decade ago