Steven Brown

Password Storage Options

by on Apr.23, 2007, under Security

Whatever web language you are programming in (PHP, ASP, etc.) you will no doubt come across the need to implement an authentication or user login system at some point.

There is an obvious need to protect passwords in some way, otherwise discovering the password field, through SQL injection or other attack, would allow an attacker to login as another user.

So the password MD5 was born. On the surface this is relatively sound, hash the password using the MD5 algorithm. The original password can never be directly retrieved from the hash so even if someone does get access to view the password field, they do not actually know the password and cannot use it directly to login.

Note: any one-way hash algorithm will mean that you cannot retrieve a password in the normal fashion, you are forced to assign a new password. This is best done randomly.

SHA1 is a good alternative, it has a longer hash length and therefore more possibilities.

Let’s think for a minute about potential attacks. Dictionary attacks are the first that come to mind for me. Their simplest form, a guess, can actually be very effective. Who would have thought gaining wireless internet access at the Beach Hotel required the username “beach” and the password “hotel”?

The first suggestion I have for you is: do not allow infinite guesses at a password. Limit incorrect guesses to 3 tries before you lock down the account. You can even email the user at this point and suggest that they reset their password.

MD5 dictionaries are known to exist, and are not difficult to create, just time consuming and large. If someone knows the MD5 of your password, they can look up a match in their dictionary. The nature of digests means that the match does not actually have to be your password. Two different pieces of data can have the same hash. This is the major weakness with the MD5 (or other single hash) option.

Some have suggested salting the MD5. This is a good idea but does still leave you open to dictionary attacks, especially if they know the salt. In open source frameworks or CMS situations a lot of people will not change the default salt, making attacks easier. If you are making a framework or CMS, set the default salt the blank and require that one be entered. Salting is good as it forces a non-standard dictionary to be created, that takes time, processing power and storage.

Note: some have suggested creating a unique salt for each user. This is not necessarily more secure as it is likely the salt can be discovered in the same way the original hash was discovered.

My suggestion here is to add a second hash algorithm. You might have both MD5 and SHA1. Now don’t be mistaken here, I mean that you store BOTH hashes in the database. This is not a combination (e.g. md5(sha1($password)) or sha1(md5($password))). When testing the password you test against both fields, both algorithms. The likelihood of a guess matching both algorithms is extremely rare and forces the attacker to be more accurate. Their dictionary now has to contain both MD5 and SHA1, and many more combinations. Their processing and storage needs have just multiplied, and all you added was one more field and one more test.

Note: some have suggested applying one hash on top of another. This can make things a bit trickier, like adding a salt, however if someone knows the process you follow they can easily recreate a dictionary based on that.

You can then salt the algorithms to add an extra bit of nastiness!

Other than that, consider the possible variations available to most users, a-z, A-Z, 0-9. That’s 62 characters. Most passwords are less than 8 characters long. That gives you 218,340,105,584,896 possible combinations. That might seem like a lot, but really that is a pretty small dictionary for a computer to process. You could force users to select a special character (`~!@#$%^&*()-=_+[]\{}|;’:”,./<>?). This results in almost 28 times more combinations.

You can also force users to have longer passwords, say 10 characters total. This results in 8836 times more combinations.

These conditions may seem unnecessary, but most people are using password remembering tools on their machines, making things a little less annoying.

Note: don’t forget to make your random password generator stick to these rules as well when assigning new passwords.

Don’t forget the “people” side of security, basically the most insecure part. Be sure to notify users about phishing and the rules you follow with regards to passwords. First of all, you would never ask for passwords in an email and you never lose passwords. Let them know exactly what URL they should expect when logging into your site. This is a really difficult area as people have a tendency to ignore everything you say and follow phishing emails blindly.

Even more difficult there are phishing attacks that can be launched from your site if you allow scripting, recently my sister got caught by a scam on MySpace that sent her to a page noting that her session had timed out and she needed to login again. She did so and soon after her entire account was erased.

When resetting a password, it might be best not to do it on first request. Instead, send an email to the user confirming they want their password reset, then reset it on confirmation. If you allow the password to be reset straight away it could create quite an annoyance for users as anyone can repeatedly reset their password.

You might also require a “captcha” when logging in or resetting passwords to minimise the effectiveness of bot attacks.

In summary, the options are:

  • Use two hash algorithms and check against both
  • Salt hash algorithms
  • Always use a unique salt for each site
  • Require special characters in passwords
  • Require long passwords
  • Inform your users about phishing
  • Do not allow users to enter scripting
  • Confirm before resetting passwords
  • Consider captchas for logging in and resetting passwords

The combination of options you choose really comes down to the sensitivity and value of the data you are protecting. I have tried to suggest a series of quick and easy solutions that amplify the difficulty for attackers.

For most sites a simple two-hash solution will be better than most options currently being utilised. If your site requires extra security then pump it right up and be very strict. Security is always a trade off with usability. The options I have suggested here hopefully do not impact too much on usability.


1 Comment for this entry

  • akrabat

    Can you explain the attack vector where having two hashes stored makes it more secure?

    Regards,

    Rob…

Leave a Reply

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!