Tools Phpass Lead image: © Michael Moeller, fotolia.com
© Michael Moeller, fotolia.com
 

Password protection with Phpass

Password Mincer

How do web applications remember passwords? They don't. They turn them into mincemeat. And Phpass, which encrypts passwords in popular web applications, helps them do so. By Tim Schürmann

The shiny, new content management system is just waiting to be fed with content by a plethora of users. To prevent them from getting into mischief, they all have to authenticate using a password. Validating the password may seem trivial, initially: the web application looks in its database for a password that belongs to the user and compares it with the password entered by the user. But, to allow this to happen, the application needs to store passwords in the clear in its database. While security-conscious admins and developers cringe at the thought, hackers already have the champagne on ice.

To implement a wiser approach, you could introduce some appropriate security measures yourself, or you could turn to some security experts for a ready-made solution. One of these solutions is the Password Hashing Framework, or Phpass [1]. It encrypts passwords in a crack-proof manner and is used by popular web applications such as the Drupal Content Management System, or the WordPress blog software – although some restrictions do apply here (more on that later). Before you can integrate Phpass with your own application, however, you should take time to look at how it works.

Hash Me!

Phpass runs every password passed into it through a special mathematical function. Just like a grinder, it converts the password into a finely ground mess. The function is designed so that it will always return the same unintelligible results for the same password entry and so that the effort involved in reconstructing the original password from the results is huge. A function of this kind is known as a hash function, and the chaotic output itself is the hash.

All the web application needs to do is to store this unintelligible hash in its database (Figure 1). When a user logs in with a password, Phpass computes the hash from the string and compares the results with the hash stored in the database.

If an attacker has access to the database, they will only see cryptic hash. In this example, PhpMyAdmin shows the Joomla Content Management System, which uses the MD5 approach with a salt.
Figure 1: If an attacker has access to the database, they will only see cryptic hash. In this example, PhpMyAdmin shows the Joomla Content Management System, which uses the MD5 approach with a salt.

Five of Trumps

All of the major web applications have used this principle for some time. Like Joomla, they all use the Message Digest Algorithm 5 (MD5) to generate the hash. A function for this exists in any PHP environment:

$hashwert = md5($password);

Unfortunately, MD5 was optimized by its inventors for fast processing. If you have sufficient computational power and know a couple of tricks, you can extract the passwords from the hashes MD5 computes. Today's multicore processors or graphics chips (GPGPUs) can compute several million MD5 hashes per second for a password and compare them with the stored hash. And, thanks to cheap terabyte hard disks, you can compute the hash for any conceivable password up front and store it in a long table (known as a rainbow table). Just like using a phone book, you only need to check which hash matches which password.

Fortunately, the PHP environment offers other, and better, hash functions courtesy of the slightly difficult to use crypt() function [2]. Which functions are actually available depends on your PHP version and operating system. Because of this, Phpass uses a multiple layer strategy. It initially tries to use the far more secure Bcrypt [3], which in turn is based on the Blowfish method. If Bcrypt isn't available, Phpass uses the Extended DES method. And if you can't use that, it falls back to MD5 with a couple of its own security extensions. The Phpass maintainers deliberately chose Blowfish and Extended DES because most systems implement them in a particularly efficient way in C.

Pass the Salt

Phpass calls the selected hash function multiple times – that is, it runs a long line of mincers. This means that an attacker will take much longer to attempt to brute force all possible passwords – eight mincers will give you a factor of eight. This process also extends the hash (known as key stretching).

To additionally increase security, Phpass uses a randomly selected string, known as the salt, when computing the hash. A different sort is used for each password entered. This approach requires attackers to store infinitely more passwords in their rainbow tables, which substantially increases the computational effort and space required. As a source for salts, Phpass uses /dev/urandom on Linux systems. If this function is not available, Phpass turns to its own pseudo-random generator. Although it is not actually designed for generating salts, the Drupal 7 content management system also uses a variant of this generator in other places.

Phpass appends a salt to the generated hash. This step is necessary because the salt has to be used again by the hash function the next time a visitor logs in; otherwise, the hash value calculated would be incorrect. Because the salt is only defined to increase the number of potential hashes, this is not a security issue.

Security Class

Phpass works with PHP 3.0.18 or newer. If you want to make sure that Phpass will use Bcrypt as its hash function, you should use PHP 5.3.0, or newer. This version is the first to integrate Blowfish, Extended DES, and MD5 in the interpreter. To add this functionality to a previous version, you can install the Suhosin Patch [4], which some Linux distributions and various BSD systems already include. Incidentally, a complete port exists for Python, and a variant with a limited feature scope exists for Perl [1].

Today, Phpass is used by WordPress version 2.5 or newer, bbPress, and Vanilla. Modified versions, and all versions restricted to the MD5 emergency variant, are also integrated into phpBB3 and Drupal 7. Extensions also exist that retrospectively add Phpass to Drupal 5 and 6, and Typo3.

Phpass mainly comprises a small PHP class that you can easily integrate into your own PHP application. Start by downloading the archive from the slightly cluttered website [1]; then, unpack the archive and integrate the PasswordHash.php into your own script:

require('PasswordHash.php');

The next step is to instantiate the PasswordHash class that this provides:

$hasher = new PasswordHash(8, FALSE);

The first parameter of the constructor defines how often Phpass should call the hash function. The value is a power of two; in other words, Phpass would run the hash function 28 times (in other words, 256 times) in this example. The highest possible value is 31. If the second parameter is set to TRUE, Phpass will always use the legacy, but salted, MD5 method. Although this approach makes the results portable and means they will run on legacy PHP installations, the downside is that the solution is less secure. FALSE tells Phpass to prefer Bcrypt instead. Web 2.0 applications that use Phpass very often allow you to modify these two settings either in the configuration file, or directly in the administration front end.

You can then use the $hasher objects to mince the password:

$password = " secret123";
$hashvalue = $hasher->HashPassword($password);

The hash value in $hashvalue is stored in the database. Incidentally, the string doesn't just contain the hash itself; it also contains all the additional information that Phpass meets later to verify the password:

$2a$08$zEIaPFIg...

The two characters that follow the first dollar sign show the hash function used here. 2a tells us that Bcrypt is being used. The number after the second dollar sign indicates how often the hash function was called in succession (as a power of two, that is, 28 = 256 times in the example.) This is followed by the salt, the length of which depends on the hash method; Bcrypt a 16-digit hash. Finally, this information is followed by the hash itself. The results produced by HashPassword() will always comprise at least 20 characters. Armed with this knowledge, you can do the following to test whether the hash function was successful:

if (strlen($hashvalue) < 20) echo "Hashing failed!";

Test

When the user logs into the same system again later, you need to pick up the hash stored in the database along with a variable, for example, $passwordfromdb, and start the test:

$password = "secret123";
$passwordfromdb = getHashFromDB();
$result = $hasher->CheckPassword($password,$passwordfromdb);

The function CheckPassword() returns a value of TRUE if the two hashes match, and the password is therefore valid. Listing 1 shows an example that you can call without a database. The Phpass archive has a more exhaustive example in the test.php file.

Listing 1: Example of Using phpass

01 <?php
02 require_once('PasswordHash.php'); // require phpass
03
04 // create new PasswordHash object:
05 $hasher = new PasswordHash(8, FALSE);
06
07 // Hash password:
08 $password = "test12345";
09 // In a production web application, the password would be retrieved from a form filled out by the user
10 $hashwert = $hasher->HashPassword($password);
11
12 echo "Password: " . $password . "\n<br>";
13 echo "Hash: " . $hashvalue . "\n<br>";
14
15 // Compare $password with the store has:
16 $passwordfromdb = '$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0';
17 // stored hash, would be in the database for a production web application
18 $result = $hasher->CheckPassword($password, $passwordfromdb);
19
20 if ($result) {
21         echo "Password match!";
22 }
23 else {
24         echo "Password mismatch!";
25 }
26
27 ?>

Something in the Air

Phpass does take some of the load off the web developer's shoulders, but it is by no means a panacea. If a user chooses his date of birth as a password, it can be guessed, and hashing will not give you security, no matter how good it is. In other words, the web application should check the length and quality of passwords that are entered. Additionally, you should use SSL to secure password transmissions. After all, it isn't much use if the web application stores the passwords safely against attacks but the communications are sniffed, in which case the attacker can just grab the password in the clear as it is typed.

An attacker can try the dictionary of passwords for each user account. To make this more difficult, increase the time between two login attempts whenever you identify an invalid password. A user who mistypes the password three times will not notice the difference, but a program that systematically tries several hundred passwords in succession can be brought to a standstill by this technique.

Finally, password security is just a small brick in the wall with any secure web application. You must still validate user input for malicious code (SQL injection) [5].

Conclusions

Phpass gives web developers a securely hashed password quickly and easily. The tool has been tested in production and analyzed by many experts, and it is available for free. Incidentally, the mastermind behind Phpass is Solar Designer (alias Alexander Peslyak), who also developed the well-known password cracker named John the Ripper. Peslyak offers other useful tips and secure web applications above and beyond Phpass [6].