Do not store passwords in Plain Text
This isn’t always obvious to novice programmers or users, but it should be. Anyone who can view the database can view the passwords as one would type them in. It gets worse because many people re-use passwords. So one compromised password could give an attacker access to not only your application but potentially many others.
What is not very obvious is how to do authentication without a plain text password. You need a method that will make the password unreadable to the attacker if he looks in the database, but you need to be able to check if the user entered the correct password. The solution is to use a one way hash function (like sha1) on the password before storing it in the database. For example, the password ‘demo’ would be come ‘89e495e7941cf9e40e6980d14a16bf023ccd4c91′. Assuming the one way hash function is indeed one way, the attacker could not reverse the hash to get ‘demo’. It is best if you call the hash function in php rather than calling the hash function in MySQL (or some other database). That way the password won’t be sent “over the wire” to a remote MySQL server. Then, when the user wishes to authenticate, just hash her password and compare the value with what you have in the database.
Salt your Passwords
Salting a password refers to changing the password before it is hashed. This can be accomplished by appending and/or prepending a string to the original password. The string should be unique and randomly generated for each user.
This helps us in the event that an attacker or user gets a copy of our database. Without salting, if two users have the same password, their hashes will be the same. If a user found out that his hashed password matched another user’s hashed password, he could use the other user’s account. That sounded confusing, let’s use an example. The hash of Alice’s password is: “c3218af382ebc0a”. Bob’s password also hashes to “c3218af382ebc0a”. Bob looks in the database and sees that Alice’s password hashes to “c3218af382ebc0a”, just like his. Bob tries his password with Alice’s user name and is able to log in as her.
By using salts, we also make the life of an attacker more difficult. Sometimes attackers build dictionaries. They take thousands of common passwords, compute their hashes, and store both in a table. They take the hash they stole from you and look it (and the corresponding password) up in their dictionary. If we have added a constant value before and/or after the password before we hash it, the attacker would have to build dictionaries for every account he’s trying to break into.
Check Password Strength
Most authentication systems allow users to pick their own passwords. The user is usually free to pick anything. Some users aren’t the smartest when it comes to choosing passwords. They might pick a common dictionary word, their user name, or they might even leave the password field blank. Depending on your security requirements, you may want to set some restrictions on the types of passwords users can choose. A good rule set is: 8 characters minimum, mixed case, alpha numeric, at least 2 upper case, at least 2 lower case, at least 2 numbers, no dictionary words, no sequences (123abcDE), must not contain a user name.
No default Passwords
So many web applications install themselves with default user names and passwords (like admin:admin). This requires the user to take the initiative to change the password. In the best case, it leaves a very small window when an attacker could use the default login to gain access. In the worst case (i.e. the user never changes the default password), the site is wide open for anyone to find. The best thing to do is have a user pick their own admin user name and password when the installation scripts run. Another choice is to generate a random password during installation.
Transmitting Plain Text Passwords
This is more of an end user configuration issue, however, I’m going to address it anyway. Usernames and passwords should not be transmitted in plain text. Anyone between you and the server could ’sniff’ your password and use it to impersonate you. As a developer there are several options. You can be passive and suggest always using SSL (https) in your documentation or you could be more proactive and refuse to work without SSL by checking that the requested url begins with ‘https’. Another option is to do client side encryption in javascript.