December 26, 2011

Salting Your Passwords


Let's imagine that I am designing a web application that requires users to log in with a password.  And for the sake of the argument, let's imagine that the plain-text password can reach my servers without being compromised -- the whole process of the user sending the password and my servers receiving it being a sort of black-box that we need not worry about.

Now, as the architect of the web application, I have decided that passwords should be stored in a database. But, if our servers are compromised, the hacker would have access to every user's password -- and knowing users, this password is probably not unique to this web application.

Therefor, the passwords can't be stored as plain-text.

We've detected a major problem with our database: every one's password is vulnerable to an attack.  The solution?  Hashing the passwords and storing the hash.  We can imagine the hashing process as another black-box that let's us put a string in and get a "random" string out.  The great thing about hashing is that similar strings hash to completely different hash values, so attackers can't predict what the plain-text password is based on the hashed value.
Imagine the hashing process as a black box.


Therefor, we should hash our passwords and store the hash.



But, we have problem.  Attackers are pretty keen.  In fact, attackers can use tools called "rainbow tables" that have precalculated hashes for common passwords so that they can look up the original password based on the hash.  There are whole websites and applications (not to mention huge databases created by hackers!) that allow people to reverse look up the hashed password.  Here is one that has reverse look ups for MD5, SHA1, and SHA256.  Yup, hackers have the tools to crack the passwords in our database.

Quite a dilemma.  We can't expect our users to give us safe and strong passwords.  So what the hell do we do now?  We salt the passwords.  Remember those look up tables?  Well, they are only precomputed for common passwords.  So, if we add a sort of "seasoning" to our passwords, attackers won't have the ability to user their rainbow tables against out database.

Therefor, we should salt our passwords before we hash them.

Here's a simple example of salting out passwords.  I'm an average user, and my password for the site is "weaselmuffin".  That is a pretty simple passwords; it's only two dictionary words.  When hashed using the SHA256 algorithm, the password is stored as:

fb41616856356b0a39cfe09330bc5f93bd222976201dc18c60261efaef75586c

And, most reverse look up websites can't resolve that hash.  But we can make it even harder to crack the passwords in our database.  Let's say we have decided to salt each password with the string "ourwebapplication717HJ%$g".  We'd get some very unique hashed passwords in our database; but if someone found our secret salt, then the attacker could just recompute the rainbow table with our salt and we would be back where we were before.
Salt passwords with unique salts.

There must be a way to make the passwords in our database more secure.

And there is: have each password salted with a different secret salt.  It's as if each entry in our database is a burger, but we've created secret seasoning for each one, making it impossible for competing burger chains to figure out the secret seasoning for every burger we make.  

Now let's finally make it easy for us: let's salt each password with the user's username!  Even though the username is easily available to the attacker, they still have the recalculate a rainbow table to account for the salt.  The attacker ends up essentially brute forcing every single password!

Therefor, we should salt our passwords with unique salts.

And that's all there is too it!  I hope that made sense.


For further reading, I suggest: "Season Your Passwords With Some Salt".

0 comments:

Post a Comment