It’s amazing that in this day and age there are still systems that store passwords in databases in clear text. Passwords should never be stored in a database, you should always store the result of a one-way encryption process known as a Hash (with some Salt!).
If you store your users passwords in clear text in a database then you’re just asking for trouble. It’s only a matter of time before a disgruntled employee gets access and keeps a copy, or it gets compromised through other poor security practices and exposed to the world. You probably won’t even know it’s been copied. And because users are dumb and reuse passwords across multiple systems, their accounts are probably compromised on many services not just yours.
So what is this hashing you speak of?
When you store a salted, hashed password you are not actually storing the password – you’re storing the output of an irreversible algorithm instead. This means when you are validating the username / password of the user at logon time you need to apply the same process to their input and compare the results. It also means that if someone downloads the database they cannot ‘reverse’ the password if they also had the key.
At logon time instead of comparing “Passw0rd1” with the User.Password property you are comparing a string that looks something like this:
The result of a Hash function is consistent – if you feed the same string in again you’ll get the same result. So if you just applied a Hash function to every password then anyone who applied the same Hash function with various random strings (or dictionary words) would be able to eventually find matches and ‘decode’ the passwords through this process. If multiple users used the same password it would also be easily spotted (not the password, just the fact they are the same) because the result of the Hash function is the always the same.
The way to add some variety to this process is to apply some Salt – add a random string to the password provided by the user and then Hash the result of that. Store the Salt with the Hash result, and make sure the Salt is different for every Hash. Simply apply the same Salt to the input string when checking the user input to see if the ‘password’ matches – remember we’re actually checking to see if the Hash result matches!
What if a user forgets their password?
Firstly tell them to use LastPass so they don’t need to remember them again. Instead of telling them what their password is, you generate an email with a long, unique token in a URL. The user clicks on the URL and your web server reads the token. You make the token valid for only a small window of time (maybe a few hours) by recording the date/time it was issued.
By clicking on the link and having the token validated you’ve verified that the user is in control of their email account (well not actually). Generate a new password for the user and display it on the screen – do not email it! The user can then decide to change it to something they can remember if they want.
You may choose to force the user to jump through some additional security hoops for verification at the landing page from the email link – usually by getting the user to provide some additional information unique to that user account that should only be known to the user and your system. Again this information should be stored Hashed and Salted, not in clear text – what is the point of storing the password in clear text if the security question answers are in clear text?
So next time you’re on the phone to a call centre operator trying to remember the answer to that weirdly worded question your bank made you answer 4 years ago and the operator gives you a hint or tells you that you’re close… well you know that information been stored in clear text (or a reversible form of encryption).
Great articles that reinforce this topic:
Salted Password Hasing – Doing it right – PHP, C#
PasswordFail.com – including a list of offending websites!