Securely store passwords with bcrypt
blog.phusion.nl
blog.phusion.nl
Also, bcrypt is pretty much the de facto industry standard adaptive password hash. It's not Phusion's crazy idea. There's a PKCS function that works on similar principles (PBKDF), but it isn't as resilient as bcrypt is.
http://blog.phusion.nl/2009/08/13/securely-store-passwords-w...
Security is all about the weakest link. There is no point dialing one of the links up to absolutely insane heights without taking commensurate measures with the rest of your links - and a salted, hashed, SHA1 password is already pretty freaking secure.
Let me give an example. If your opponent possesses the incredible resources necessary to brute force SHA1 in a useful timeframe - and there are probably only a handful of such organisations on earth, all governmental - then they will not even bother with that. They will simply bug your server and collect the passwords plaintext somehow there. Or they'll subpoena you and force you to start collecting the plaintext. Hell, what do they need the passwords for anyway?
See what I mean? It's solving the wrong problem. Anyone who could actually brute force SHA1 is such a formiddable opponent that they could not care less if you changed to bcrypt or whatever. You have already lost if they even decide to mess with you.
Plus, it's yet another dependency. And then the speed penalty. Forget it. Put the time into setting up SSH keys or turning off root login or something; you're a million times more likely to be compromised by those kinds of everyday flaws than NSA-level shit like this.
Consider, most users of web sites have pretty simplistic passwords. The salt needs to be known in order to validate the password, probably stored in the row with the password. If the password database is ever compromised, it's then trivial for an interested party to start pounding salts and hashes through something like http://nsa.unaligned.org/ or a botnet of compromised machines.*
Sure security might be about the weakest link, but you also have to look at the value of each loss. You're opening yourself up to a firestorm of embarrassment if your user table is leaked (so your argument about securing everything else is important) but that's so much worse when decrypted passwords are going around with the table.
[*] The winners of the Engine Yard SHA1 challenge http://www.win.tue.nl/cccc/sha-1-challenge.html did almost 700 MILLION SHA1 hashes per second on two beefcake video cards.
But it is not enough to know the salt. A correct implementation also includes a (lengthy) pepper, stored in the application code. If you've got that as well, and also details of how the particular hashing setup works, then it is indeed probable you would be able to brute force the hashes.
But my point is, if someone has enough access to get all that, then they can probably just silently suck off the passwords in some way anyway. They are obviously in the machines and are probably root. They could probably insert code right into your app to email them every new password coming in, pre-hashing, and you wouldn't learn about it for months.
And if they only have the user table - well, 700m hashes a second is very impressive indeed but that's still 2.7 × 10^36 seconds to brute force a 32-character pepper.
You might still think it's worth it - defence in depth and all that. But considering the price you pay, like its slowness - 0.1 seconds might sound fast but if the server's running at load then it will be more - and the hassle of having another gem, especially one with a C dependency, I do not agree.
update: actually, upon further consideration and research, fine. I'll switch to bcrypt too from now on. That's a huge gain and the cost is not that high. I guess it hadn't sunk in just how fast SHA1 implementations were getting.
I still maintain it's not the weakest link - the weakest links numbers 1 through 50 are staff - but it's a definite improvement with little cost.
Of course you would not depend upon it solely but it's called defence in depth.
To evaluate the efficacy of a "defense in depth" measurement, insert it into an incident disclosure. For instance:
"We're sorry to inform our users that owing to an SQL Injection vulnerability, we may have disclosed the password hashes of all of our users. We believe these passwords remain safe, because an attacker would also need to have access to our source code in order to learn the secret key needed to mount a dictionary attack against them."
Compare to:
"We're sorry to inform our users that owing to an SQL Injection vulnerability, we may have disclosed the password hashes of all of our users. We believe these passwords remain safe, because the cryptographic algorithm used to create the hashes ensures that it would take over 100 years to complete a dictionary attack against a single password."
Firstly, even in the first "disclosure" message - the passwords are indeed safe. Because of that "useless" peppering, there is no way the attackers will be able to unmask the hashes.
Secondly, if you have configured your database such that it is even possible to perform a select all on Users from the app server account, you are Doing It Wrong.
However, you are broadly right.
That said - my whole thesis here is that there are no magic bullets. Yes bcrypt is (much) better against this particular attack. But the DB server is not even web-facing and is unlikely to be compromised; the app servers are far more risky. They have access to the plaintext passwords flowing through them. When they are rooted, you're fucked no matter what hashing strategy you chose. And if you have a crooked insider - which as a security professional, you will know is by far the more likely risk - that's where they will strike as well, of course. Your precious passwords will be bcrypt hashed to the DB all right, but Mallory keeps his own plaintext backup, written by the comped bcrypt gem he snuck onto the system looking for a payday. Or whatever. There's a million ways to do it, all of them easier than brute forcing anything. You're focusing on this single scenario to the exclusion of any number of more likely attacks. Despite the hype, "steal-the-user-table" breaks are not common.
Anyway. I was wrong, and I admitted it. Use bcrypt, everyone. EOF
You and I both know this attack is about running a dictionary of possible passwords against a stolen password database, and, because you seem smart (if annoying), I'm pretty sure you also know that attack is lightning fast. You also seem young, so you might not realize that this attack was the "industry standard" password cracking mechanism throughout the entire 1990s; it's the attack that Crack and John The Ripper are based off of. Before the crappy LANMAN hash, it was the only password attack Unix hackers had available to them, and it was so effective that every Unix system had to implement "shadow" passwords.
Please stop trolling, sho.
However, I've actually changed my mind and conceded defeat on this one. If the attacker could grab a copy of the app code as well and get the pepper & hashing setup, bcrypt would indeed slow down the ensuing attack on the passwords. You're basically screwed by then, of course, but it would be nice for the users if they had a little while longer to change their passwords on other sites.
I'll be using bcrypt from now on.
Also, there's no such thing as "pepper", despite what the PHP forums may say.
If you weren't deliberately misleading developers into using insecure code patterns, I'd just ignore you, sho.