Monday, November 26, 2012

PHP/MySQL: Easy Solutions to Protecting Passwords in a Database


One of the most common errors that a novice PHP/MySQL programmer will commit when creating a membership site is storing passwords in the database without securing them in some way. Why is this a problem? If a database is hacked, and this can occur easily without sufficient safeguards throughout the code of the entire website (one loophole and it could be accessed and the information harvested), a hacker could easily discover all over your users' passwords and not only use this information to take control of their accounts (including admin accounts!) but also accounts of other services of which a user may be using the same password (Gmail, Facebook, Twitter, PayPal, you name it!).

Perhaps an attack this drastic isn't as much of a problem if you have good code that prevents SQL injections and the like, but there is still the brute force or dictionary attack options that hackers could use to get a user's password, including the admin's password. It is therefore important for your own site and the privacy and safety of your users to ensure that your passwords are safely stored in your database. When a user gives you his password, he is expecting it to be safe; so don't let your users down!

There are many ways a PHP programmer can encrypt passwords before storing them in the database. The most common method is using a hash, which means that the process of encrypting a password cannot be reversed; so if a user loses her password, she must be given a new one as the old one cannot be decrypted and given back to her. Hashed passwords are usually checked during login in the same manner that an unencrypted password is: by comparing strings. There are exceptions to this method in stronger hashes, which I'll get to.

The easiest method (and a very common one) is through the use of md5 to encrypt the password. Though this method is incredibly easy, and certainly preferable than nothing at all, it is not very difficult to break the encryption, and there are many sites that help in doing exactly this. I tried one of these sites once, to great success.

But, if you feel this method will be secure enough for your site, at least for the time being, this is how it would be done:

$encrypt_pass = md5($pass);

Where $encrypt_pass is the encrypted password and $pass is the variable containing the password you wish to encrypt. But since this method is fairly insecure, let's look at other options.

A very similar but slightly better hash is sha1. It works in much the same way as md5 does, except it returns a 160-bit fingerprint rather than a 128-bit fingerprint:

$encrypt_pass = sha1($pass);

Another option is using a salt on top of md5 or sha1. The way this works is that a string is added to the password before md5 or sha1 hashes it. This is fairly good to prevent brute force or dictionary attacks, as the theory behind it is that a user's weak password can be strengthened by the salt before being hashed and inserted into the database. For example:

$pass = "pass123";//Let's say this is the password the user entered

$salt = "1y2Jdu1D8!b";//This is the salt algorithm

$encrypt_pass = md5($salt$pass);//We add the salt and hash

If the hacker can discover what the salt algorithm is, however, this method is just as weak as an ordinary md5 or sha1 hash. So what else can we do? How about combining methods?

$pass = "pass123";

$salt = sha1(md5($pass));

$encrypt_pass = md5($salt$pass);

Though this is not foolproof, it's really strong, and nearly impossible to crack without knowing the algorithms, which usually means access to the .php file. Of course, if you want to keep these passwords safe from others who may be working on a project with you and do have access to the files, there is yet another option to consider.

I personally like to use the "Portable PHP Password Hashing Framework" or phpass, an open-source solution on which password encryption for phpBB and WordPress is based on. With this system, a hash is different every time for the same password, meaning that one must use phpass's function to compare two passwords. Theoretically this makes it impossible to decrypt.

In order to use this framework, you must download the files from openwall. There will be a PHP file there called PasswordHash .php that has the hash class. Upload it to your server and require (or include) it on the page where the password will be encrypted. You can then call the class to hash the password:

$t_hasher = new PasswordHash(8, FALSE);

$hash = $t_hasher->HashPassword($pass);

Then, to check two passwords (during login for instance):

$check = $t_hasher->CheckPassword($pass, $hash); //$pass is the password being check and $hash would be the hashed password stored in the database

if ($check){ /*Let the user through*/ }

if(!$check){ /*Don't let the user through*/ }

The test .php file is well commented and will have more functions that may be useful to look over. It will also test everything to make sure it's working on your system.

So that's a quick rundown of what you can do to keep your site and your site's users safe. Please, please don't just store the passwords as plain text in your database. It's bad practice and it's not keeping the trust your users have in you when they register on your site. It's easy to do, and highly important.

An Explanation of CISPA for Small Businesses   Protect Your Privacy With Reputation Management   Top 5 Reasons to Check Website Security   Why Ignoring IDS Could Lead to Substantial Damage for Businesses   



0 comments:

Post a Comment


Twitter Facebook Flickr RSS



Français Deutsch Italiano Português
Español 日本語 한국의 中国简体。