PHP Password Security and Storage

Originally Written for PHPadvisory.com in approximately 2009

Introduction
How secure IS secure enough? There’s no such thing. Period. Even the most secure systems created by the top experts can have a weak point. Despite the fact that passwords need to be treated seriously, many programmers have habits they are stuck with, or they fall into many misconceptions. There are 4 main places where password security needs to be addressed: what the user can type in, when the password is sent to the server, what your program does with it, and how it is stored.

User Related Issues
More users than you would guess have a tendency to type in very short passwords, passwords that are in a row or pattern on the keyboard, their own names, or an easy to remember word. Many users use the same password everywhere they go. These days there are just so many to remember, it’s close to impossible. Many users who have a lot of passwords to manage will write them down somewhere. You can’t stop them from writing it down… but you can restrict what they can choose. A good idea is to put a minimum length of 6 or 8 characters. A better idea is to also require letters and numbers. An even better idea for security (although your users will hate you) is to provide randomly generated passwords. Regardless of how tough you want to get… at LEAST make sure they can’t choose ‘asdf’ as their password.

A related issue is the use of a ‘remember my password’ feature. Is this REALLY necessary? Many users forget to log out when at public terminals. I have seen sites (like a popular online bookstore) where the ‘log out’ feature was so hidden that I had to email them to ask how to log out. Make sure that your users can easily log out and that they receive confirmation that they truly are logged out.

Transferring The Password
To use a secure connection or not to. That is the question. How sensitive is your information? Is it worth it for someone to try to grab the password on it’s way to the server? If so, you might want to consider getting an SSL cert. to protect the information between browser and server. Consider what someone will achieve or gain if they get someone’s password: a forum login or personal banking information?

A related issue is the use of a ‘remember my password’ feature. Is this REALLY necessary? Many users forget to log out when at public terminals. I have seen sites (like a popular online bookstore) where the ‘log out’ feature was so hidden that I had to email them to ask how to log out. Make sure that your users can easily log out and that they receive confirmation that they truly are logged out.

Handling The Password
Once you have the password in your script’s greedy little hands, what do you do with it? Many, many, many developers think that once it’s on the server- it’s safe. Wrong. The number of worms and viruses that have been sneaking their way onto servers is proof enough that storing passwords as plain text is bad, bad, bad. But people still do it. Websites hosted on shared servers are at risk from malicious users. I cringe every time I do a select statement on a ‘users’ table and see plain text passwords. Just don’t do it. A great way to show a developer’s inexperience is by making this mistake. It’s considered sloppy- especially since better ways are so simple.

At the bare minimum, create a simple one-way hash (for example md5, Sha-1, etc) of the password and store that. PHP has built in functions for this. It’s quick and easy. For people more serious about security, or people who are just more paranoid. Hash it twice. Or append a ‘secret’ string to it and hash that. Or combine the username and password in some way then hash and store the result. The longer you make the string to be hashed the better- just don’t go crazy and append an ebook to it or you’ll get speed issues.

I’ve seen passwords that were ‘secured’ by XORing them, or ones that were reversed then stored. Gee, I wonder what ‘drowssap’ is? Don’t make up your own securing algorithm. There are optimized ones already in existence that have proven their worth. Feel free to exercise your creativity before hashing them however. Just remember you’ll have to do this each time you validate someone’s login information.

Hashing should be combined with the requirement that users choose hard to guess passwords. I’ve already learned to recognize the md5 of the word ‘test’. Shorter passwords can sometimes be vulnerable to brute force attacks, so make sure they are at the very least 6 characters long.

Storing The Password
Try very hard to resist the idea of storing passwords in a file called passwords.txt. Just don’t do it. I know you’re rolling your eyes, but it happens all the time. It’s just so easy to find and view. Don’t call it pass.txt, users.txt, logins.txt or any similar variation. If you HAVE to store it in a file then be as obscure as possible. Don’t keep the file in the web root. And if possible, store it as PHP or some other format so that if someone finds it, it’ll look like a blank file. Better yet, use a database.

Storing login information in a properly set up and secured database is your best option. It provides an added level of security, and can grow as your application grows. Woops- need to add a signup date column? Easy as pie. Try to fight the urge to name the table users or passwords or logins or something similar- it never hurts to be a little paranoid.

How Does This Relate To PHP?
This information about passwords can be applied generally to any programming project in almost any language. So why PHP specifically? Many new or inexperienced PHP programmers are under a misconception that PHP is a level of security all on it’s own. I’ve seen countless posts on message boards by ‘newbies’ claiming things like "Why do I have to worry about this? PHP is secure!" or the famous comment: "No one can see my source code- so it’s already secure!"

Many new PHP programmers – especially those accustomed to trying to make pages secure via JavaScript will often put simple hard coded passwords into their source code to secure their sites under the belief that since the source code isn’t visible, the site is perfectly safe. Don’t fall into this trap. An error on the server could cause it to stop parsing PHP and suddenly your source code is available for all to see. Sometimes this will be a temporary problem that your hosting provider may catch and fix before you even notice. But someone else may have. Doing a quick check via a search engine for the text of some common PHP errors or commands will reveal many sites with errors and code showing. Sometimes cashed versions of sites will show the full source which may have been grabbed by a search engine spider during the brief time it was available. You can’t be sure your code will be a secret.

Conclusion
One of the most common uses of PHP is to develop backend areas and private sections for websites. An important part of security is the handling of passwords. As programmers we have to fight the habits of users who are sick of memorizing dozens of complex passwords. If you find yourself saying "That’s good enough", take another look. Make sure you are taking the paranoid approach. Always match your level of security to the value of what someone would ‘get’ if they break in. Treat the handling of passwords as your first line of defense.