We’ve all heard about some of the biggest websites in the world being hacked in the last few years, be it LinkedIn, Yahoo or anyone else.
The big deal when sites get hacked is that generally it means those who did the hacking have access to the site’s database, which contains all of the information held by the site about its users; which generally includes password information.
The real problem with this is that many websites still don’t use the best practices when it comes to securing password information, and some still store passwords in their databases without any form of encryption. This means that when a hacker steals a database – they’ll have the email and password of that user, which they can go on to use on any site where the user has the same password.
Correcting this poor practice is easy though, and I’ve developed a quick PHP & MySQL script that sites can use to rectify this quickly.
All you need to do is download the Gist, enter your database information in the file, create a new pepper (more on that later), and then upload the file to your server. Then visit the location of the file on your server and the script will do its’ magic. All that’s left then is to tweak your login process slightly and your application will be secure.
So how does this all work? I’ll break it down for you.
The secure_pass_script function controls all the other functions we need to run, so this is the part that you’ll need to check runs okay. It’s a good idea to comment out line 33 of the file after you’ve run this once, or delete the file altogether, as any time this file is accessed the whole script will run and all passwords will be replaced.
The get_old_passwords function does what it says on the tin, it will go through your user table and get the user id and password and put it into an array so we can perform our securing functions on it.
The secure_passwords function is where the real action happens. Here, we create a unique salt for each user – which is a random string we’ll use when generating the new password to make it stronger.
After we’ve created the salt, we go on to the important part: creating the new password. We’ll do this by using PHP’s password_hash function, which takes an input and creates a unique hash which is a 60-character string of seemingly random characters that can only be created by entering the right password.
Any web application could use this with a password alone, but because putting the same password through this function will produce the same output on any site, it still means a hacker can guess a user’s password from a database entry if they have a dictionary of common passwords and their corresponding hash values.
What this script does then is take the user’s old password and combine it with the user’s unique salt (which a hacker will only find out if they have access to the database) and a pepper which we define in the website’s files (which a hacker will only find out if they have access to the site’s files) and then put this combined string into the password_hash. This will result in a secure password that only someone with complete control of a website can decipher.
Our final function, save_secure_passwords will go back into the database and firstly create a new salt column (if it doesn’t exist already) and then save the passwords and salts there.
The final bit of work you’ll need to do is tweak your login verification process, using the verify_passwords function. Here you input the username (or something else) and the password the user supplies to login, and then check to see if it matches in the database. This function will first check that the user exists, and then if they do it will combine the supplied password with the user’s salt and the website’s pepper to re-create a hash. If this new hash matches what we have saved as the user’s password, then the user can login. If any part of this fails, then the user won’t be able to log in.
You can download the Gists for the secure password script, the login function and create user function below and use them to make your site more secure. Please test it with some sample data using your database user table’s structure first to iron out any bugs, and after that run a test of it with a copy of your actual database to make sure everything works okay before running it on a live site. I assume no responsibility if the script goes wrong, test first to make sure!
If you’ve got any feedback on how to make this more secure or how it’s worked for you, feel free to leave a comment below.