Protecting Your Users’ Passwords

I’m currently working on a PHP-based web site that stores member details – username, address, password etc in a database. Nothing unusual here… literally millions of web sites on the internet are doing exactly the same thing.

But password storage is a dangerous area. Every month we hear about a high-profile web site being hacked into and all the user accounts made public together with their passwords. This is not good – especially as it’s fairly common for users to keep the same password across all of the sites they access.

Good web site security is about defence in depth. Yes, you set up security so that hackers hopefully can’t get access to your site’s files and databases. But you shouldn’t stop there. Any site whose password list has been published has made one other simple and easily avoidable mistake: they’ve made the mistake of storing their users’ passwords in plain text.

Storing passwords in plaintext is a dangerous mistake that’s easily avoided – there’s a much smarter way to do it and it involves something called a hashing algorithm. A hashing algorithm is a form of encryption which is ONE WAY i.e. you can convert the plaintext to the encrypted form (know as ciphertext) but you can’t convert it back again. For example, if you start with “donkey” and run it through a well-known hashing algorithm you end up with “9443b0fceb8c03b6a514a706ea69df0b”. In theory, there’s no easy way to go the other way and turn that back into “donkey”.

But how the heck does this help us with passwords? Surely we’re going to have to turn the encrypted password back to plaintext in order to check it? Nope – there’s a neater way of doing this.

When the user initially sets their password, we run the hashing algorithm on the plaintext password and generate a hashed version of it. We store that hashed version in our database. When a user attempts to login, we hash their password attempt and compare THAT to the ciphertext of the previously hashed password that we’ve stored. Because the hashing algorithm is repeatable, if the password they attempted to login with matches the password they setup originally, then the two hashed ciphertexts will match too and we’ll successfully validate their login.

There’s no excuse for not knowing about this design pattern – Unix & Linux systems have been handling user passwords in this way for the last 30 years.

When you implement a system like this, there’s one thing you CAN’T do. And that’s recover a password that a user’s forgotten. Remember that the hashing algorithm is one way. You can’t turn “9443b0fceb8c03b6a514a706ea69df0b” back into “donkey” when the user can’t remember their password. As a result of this you should, as a user, be very wary of any websites which offer to email you your password when you’ve forgotten it. If they can email your password to you then they’re not using a hashing algorithm to store it in their database and therefore their database is not secure should a hacker get access to it. As a programmer, if you use a hashing algorithm to safeguard your users’ passwords then all you can do if a user has forgotten their password is to generate a new one for them (or let them set a new one themselves). This is generally done via an email that you send them – either containing a new random password that you generated for them or (better still) a one-off link that gives them access to a special page on the website where they can set a new password.

OK then, we’re sorted are we? Everything’s secure and protected from the hackers? Unfortunately not.

DO NOT IMPLEMENT WHAT I’VE JUST DESCRIBED.

There’s a flaw and I’ll tell you in a few days what that flaw is. In the meantime, you might like to paste that ciphertext into your favorite search engine and wonder about what just happened.

1 comment to Protecting Your Users’ Passwords