Tuesday, 20 October 2009

Password handling and hashing

A lot of people take a very simplistic or optimistic view on security. You assume that no-one will ever hack your system (perhaps there is no obvious reason to do so), you trust everyone who works for you or you simply don't really think about it. One of the most serious problems is the handling of passwords. Here are some facts that you might not know about password best practice.
  1. People often use the same passwords for more than one site so if you allow access to human-readable passwords from your site, it migth well compromise something of higher value like ebay, hotmail, banking etc.
  2. You must use defence in-depth. Just because you think that your database is secure doesn't mean you can stored passwords in plain text. Using this approach, if somebody does hack in, they then have an open door to do whatever they want.
  3. Although it is hard to hack a hashed password, it is not impossible. (hashing is obscuring it in a way that makes it very difficult to find the original value). A hacker only needs to find a word with the same hash regardless of whether it is the actual password. Some people run machines 24-7 building a list of word-hash pairs so it can reverse lookup hashes. For this reason, you should salt your hashes. This means if somebody chooses a password of, say, "PrettyBoy", before hashing it, you change it in some known but secret way like add the characters "123" to the end (or preferably something more obscure) before hashing. Suppose then the hash of "PrettyBoyab145" is ABC123, even if a hacker discovers this (which would require knowing which hashing algorithm you use) and does a reverse lookup for the password, he finds "PrettyBoy123", types it and the password fails because checking the password "PrettyBoy123" adds the salt "123" to get "PrettyBoy123123" which when hashed (e.g. XYZ456) and compared to the stored value of ABC123 will not match. Of course with a simple salt, the hacker might guess the actual password but if you add a number to the bytes of the password then this will be much harder to decipher since reverse lookups against standard hashing algorithms will probably produce garbage which won't look like a real password.
  4. You NEVER need to store plain text passwords. If someone forgets the password, use a reset mechanism. Ask them a question or two, use their registered email address and allow them to set a new password but make sure the system cannot even theretically allow a hacker to call the reset function against someone elses account. e.g. the stored proc that resets the password should look something like: procResetPassword(varchar @account, varchar @email, varchar @answer1, varchar @answer2, varchar @newpassword, varchar @newpasswordconfirm). A hacker cannot know all of these, if he does then he can simply use the normal "forgot password" page and wouldn't need to hack in the first place.
  5. You need to stay up to date with the latest knowledge concerning hashing algorithms. As technology gets faster, older algorithms tend to become insecure because it takes less time to reverse them by brute force. You don't need to update the minute somebody suggests a weakness but once a year checking and upgrading can be useful. Bear in mind, this will affect existing passwords so you would either need to know which hash to use for a given user or have to get all users to reset their passwords.
  6. Even having a good backend system does not prevent somebody snooping on the transmission between the web page and back end when by default information is sent plain text. You should consider redirection to HTTPS (SSL) for login, even if you then redirect back to standard HTTP. This way, there is encryption between client and back end.
  7. Even if the transmission is secure and you have a secure backend, a session is generally only a cookie so it is usually easy for somebody to jump straight onto a machine used by somebody else and gain access to the site. Cookies might also be stored and reused later. Ensure you understand sessions. Always provide an accessible logout button which wipes the session and try and use existing libraries instead of rolling your own. Allow others' mistakes to improve your code.
Play safe!