Cleansing User Passwords

Cleansing User Passwords

You should never escape, trim or use any other cleansing mechanism on passwords you'll be hashing with PHP's password_hash() for a number of reasons, the single largest of which is because doing additional cleansing to the password requires unnecessary additional code.

You will argue (and you see it in every post where user data is accepted for use in your systems) that we should cleanse all user input and you would be right for every other piece of information we're accepting from our users. Passwords are different. Hashed passwords cannot offer any SQL injection threat because the string is turned into hash prior to storing in the database.

The act of hashing a password is the act of making the password safe to store in your database. The hash function doesn't give special meaning to any bytes, so no cleansing of its input is required for security reasons

If you follow the mantras of allowing users to use the passwords / phrases they desire and you don't limit passwords, allowing any length, any number of spaces and any special characters hashing will make the password/passphrase safe no matter what is contained within the password. As of right now the most common hash (the default), PASSWORD_BCRYPT, turns the password into a 60 character wide string containing a random salt along with the hashed password information and a cost (the algorithmic cost of creating the hash):

PASSWORD_BCRYPT is used to create new password hashes using the CRYPT_BLOWFISH algorithm. This will always result in a hash using the "$2y$" crypt format, which is always 60 characters wide.

The space requirements for storing the hash are subject to change as different hashing methods are added to the function, so it is always better to go larger on the column type for the stored hash, such as VARCHAR(255) or TEXT.

You could use a complete SQL query as your password and it would be hashed, making it unexecutable by the SQL engine e.g.,

SELECT * FROM `users`;

Could be hashed to $2y$10$1tOKcWUWBW5gBka04tGMO.BH7gs/qjAHZsC5wyG0zmI2C.KgaqU5G

Let's see how different sanitizing methods affect the password -

The password is I'm a "dessert topping" & a <floor wax>! (There are 5 spaces at the end of the password which are not displayed here.)

When we apply the following methods of trimming we get some wildy different results:

var_dump(trim($_POST['upassword']));
var_dump(htmlentities($_POST['upassword']));
var_dump(htmlspecialchars($_POST['upassword']));
var_dump(addslashes($_POST['upassword']));
var_dump(strip_tags($_POST['upassword']));

Results:

string(40) "I'm a "dessert topping" & a <floor wax>!" // spaces at the end are missing
string(65) "I'm a "dessert topping" & a <floor wax>! " // double quotes, ampersand and braces have been changed
string(65) "I'm a "dessert topping" & a <floor wax>! " // same here
string(48) "I\'m a \"dessert topping\" & a <floor wax>! " // escape characters have been added
string(34) "I'm a "dessert topping" & a ! " // looks like we have something missing

What happens when we send these to password_hash()? They all get hashed, just as the query did above. The problem comes in when you try to verify the password. If we employ one or more of these methods we must re-employ them prior to comparing them with password_verify(). The following would fail:

password_verify($_POST['upassword'], $hashed_password); // where $hashed_password comes from a database query

You would have to run the posted password through the cleansing method you chose before using the result of that in password verification. It is an unnecessary set of steps and will make the hash no better.


Using a PHP version less than 5.5? You can use the password_hash() compatibility pack.

You really shouldn't use MD5 password hashes.

What should I do to protect user information as non-company?

For PHPMyAdmin

  1. Change the default admin user
  2. Lock the access page to PHPMyAdmin using .htaccess
  3. Do not call the folder PHPMyAdmin
  4. Use virtual directory settings in Apache to prevent browsing of directories, or have dummy index.php in all folders

MySQL Security

For MySQL security, create a new database user with the minimal security rights for your application to work - in cases when your PHP scripts are comprised, the damage can be contained.

PHP

Cross site scripting and MySQL injection are still common issues too - there are various PHP libraries (free!) which helps to sanitize input.

If you do allow user's uploads, set the permissions for those folders to 755, and ensure PHP can read such folders - some web hosts insist folders to have permission 777 before PHP can write to them. Avoid such hosts at all costs.

If you really wish to go an extra mile, you can encrypt sensitive information as a deterrent, though the attacker probably has all the time in the world to crack those info.

Consider using PHP frameworks that would have done the legwork for basic security, such as sanitizing of POST, GET and etc.

Using hashing to safely store user passwords

you need to hash the user input password and compare hashes.

how to make password 7 characters (validation)?

This is where its messed up:

if (strlen( ($_POST['frmPassword1']) < 7 ) {

Let's start that statement over.

First you want the string represented by form field frmPassword1:

$_POST['frmPassword1']

Then you want the string length:

strlen($_POST['frmPassword1'])

Then you want to compare it to less than 8 because you specifically asked for more than 7 characters. Therefore, your expression would be:

strlen($_POST['frmPassword1']) < 8

Now make that a complete condition like so:

if( strlen($_POST['frmPassword1']) < 8 ){
//insert relevant code here telling users password is too short
}

Now you have a working block of code.



Related Topics



Leave a reply



Submit