Recently, the folks behind Reddit.com confessed that a backup copy of their database had been stolen. Later, spez, one of the Reddit developers, confirmed that the database contained password information for Reddit’s users, and that the information was stored as plain, unprotected text. In other words, once the thief had the database, he had everyone’s passwords as well.
Had the folks at Reddit salted and hashed the passwords and then stored the salts and resulting hashes in the database instead, the thief would now be in a very different situation. Instead of holding all the keys to the kingdom, he would face the prospect of a potentially expensive search for each and every user’s password he wanted to extract from the database. The expense of the search would likely have dissuaded him from making the attempt in earnest, given how little exploitable value a Reddit account represents. In short, the passwords would have been secure, even though the database had fallen into the thief’s hands.
Why, then, didn’t Reddit’s programmers salt and hash the passwords? Because, according to the earlier post by spez, they wanted to be able to send forgotten passwords to users via email. It was a design decision: they weighed the risks of having plain-as-day passwords in the database against the convenience of being able to email users their forgotten passwords and decided that, in the balance, convenience carried more weight. It’s a decision they now regret. (It’s a doubly unfortunate decision because the reasoning behind it is faulty: you don’t need to store passwords in your user database in order to offer convenient account recovery.)
The reason I’m writing about this event isn’t to kick the good folks at Reddit while they’re down. Rather, I’m trying to make a point:
If you are storing passwords in a database, you are almost certainly making a mistake.
The guys at Reddit are known for being smart. They thought they had a good reason for storing passwords in their database. They were wrong. If smart programmers can make this mistake, lots of programmers can. Do you think you have a good reason for storing passwords in your database? If so, you’re probably wrong, too.
How can I be so sure? Because, when it comes to web-app authentication, cutting corners doesn’t buy you anything. It doesn’t save you coding time. It doesn’t give your users a better experience. All it does is weaken the security of your web site, needlessly putting your users, your employer, and yourself at risk.
So please let me take this opportunity to ask if you know of (or perhaps work on) any software systems that store passwords in a database. If so, fix your software now:
- Salt and hash each and every password.
- Use an expensive hashing function such as bcrypt that was designed for password applications.
- Store the salt and hash – not the password – in your database.
- Throw the password itself away.
You’ll be glad you did.
Update: Minor edits for clarity.
Update 2007-02-13: Salting and hashing does not get in the way of account recovery. You do not need to email users their forgotten passwords: there are other account-recovery options that are just as convenient but much more secure. See Don’t let password recovery keep you from protecting your users for more.
Update 2007-10-03: Revised text slightly to emphasize that there is no benefit to be had by implementing a weak password system, and therefore there is no reason not to implement a secure system. Pointed more directly to bcrypt, too.