WordPress is one of the most popular open source web applications used by major Fortune 500 companies as well as many independent websites and blogs. Like many web applications, WordPress stores user accounts in a MySQL database, including administrative user accounts with their associated password hashes. A closer inspection of the method chosen for hashing passwords in WordPress offers an critical view of how secure or insecure the hashing methods in place are for such high profile and widely used software.

Way back as of WordPress 2.5 (March 2008), phpass (http://www.openwall.com/phpass/) has been used to hash passwords for storage in a MySQL database. phpass was written by Alexander Peslyak (aka Solar Designer), founder of the Openwall Project and creator of John the Ripper who is perhaps one of if not the authority on various hashing algorithm technologies. phpass is used by WordPress, Vanilla, phpBB, Drupal, and many other applications for password hashing.

phpass

phpass utilizes three components for password hashing:

- Hash algorithm (blowfish, DES, or MD5 in that order if available)
- Salt (random unique salt generated for each password)
- Iterations or password stretching (a specified number of iterations or rounds set as desired)

To obtain the highest level of security with phpass, the server must be running PHP version 5.3.0 or later. This is because particular PHP algorithm code is only included in 5.3.0 and later. Specifically recommended is PHP 5.3.0 or later with the Suhosin security hardening patch (http://www.hardened-php.net/suhosin/).

Ubuntu and Debian Linux include the Suhosin PHP patch via the package php5-suhosin. Red Hat Enterprise Linux 5 and 6 and likewise CentOS 5 and 6 do not include this patch by default and it must be compiled manually for those distributions (http://www.cyberciti.biz/faq/rhel-linux-install-suhosin-php-protection/). Note that Debian is considering removing Suhosin patched PHP from their distribution, so future patching may be required ( http://lwn.net/Articles/479716/ ). Suhosin has unfortunately not been well maintained, so Debian and other distributions are removing its support.

Ubuntu 10.04 Server LTS (released 24 April 2010):

$ php -v

PHP 5.3.2-1ubuntu4.17 with Suhosin-Patch (cli) (built: Jun 19 2012 01:35:33)

Copyright (c) 1997-2009 The PHP Group

Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies


Want to learn more?? The InfoSec Institute Ethical Hacking course goes in-depth into the techniques used by malicious, black hat hackers with attention getting lectures and hands-on lab exercises. While these hacking skills can be used for malicious purposes, this class teaches you how to use the same hacking techniques to perform a white-hat, ethical hack, on your organization. You leave with the ability to quantitatively assess and measure threats to information assets; and discover where your organization is most vulnerable to black hat hackers. Some features of this course include:

  • Dual Certification - CEH and CPT
  • 5 days of Intensive Hands-On Labs
  • Expert Instruction
  • CTF exercises in the evening
  • Most up-to-date proprietary courseware available

If using PHP 5.3.0 or later with the Suhosin patch, phpass has the ability to hash with blowfish (CRYPT_BLOWFISH in PHP), falling back to DES hashes if using PHP 5.3.0 and no Suhosin patch (CRYPT_EXT_DES in PHP), and a final fallback to salted MD5 based hashes (known as portable hashes). phpass utilizes iterations and salt regardless of which algorithm is utilized.

Regarding salts, phpass takes care of the complexity of adding salt to hashes. The function HashPassword() generates an eight-character random salt for each password, encoding the salt into the returned hash value. The function CheckPassword() checks against the hash that includes the salt, and it just works.

For iterations or rounds, the exact number can be set as desired by the web application. For example WordPress uses 8192 iterations and Drupal 7 uses 16384 iterations with phpass for password hashes.

WordPress Hashes

WordPress has chosen by default to use the final fallback in phpass known as ‘portable hash’ which are salted MD5 hashes. The file /wp-includes/pluggable.php outlines the call to 8192 iterations of MD5 from phpass. Remember that phpass also takes care of adding in the salt so salt is included with the hash for added security.

http://core.trac.wordpress.org/browser/tags/3.4.1/wp-includes/pluggable.php

1411 function wp_hash_password($password) {

1412     global $wp_hasher;

1413

1414     if ( empty($wp_hasher) ) {

1415     require_once( ABSPATH . ‘wp-includes/class-phpass.php’);

1416     // By default, use the portable hash from phpass

1417     $wp_hasher = new PasswordHash(8, true);

1418     }

1419

1420     return $wp_hasher->HashPassword($password);

1421 }

1422 endif;


The file /wp-includes/class-phpass.php is more or less a copy of the phpass.php source that WordPress calls. This file can be viewed at the following link:

http://core.trac.wordpress.org/browser/tags/3.4.1/wp-includes/class-phpass.php

A WordPress 3.4.1 hash looks like the following:

$P$BZtq.o.Pu99rMMBGbJ640XUZ2kVf3v.


The use of MD5 and the final fallback of phpass for WordPress password hashing is undoubtedly a choice of compatibility. MD5 is the only hash algorithm able to be used with older versions of PHP (way back to 3.0.x) as well as current PHP versions so that WordPress is able to install and run on virtually any PHP installation.

Change WordPress Default Hashing Algorithm

It is possible to change preferred algorithms for WordPress to a stronger choice than MD5. The following page outlines the needed change to /wp-includes/pluggable.php to use to blowfish if available, then falling back to DES with 16384 iterations. All users would need to change their passwords after this edit to be rehashed with the new algorithm:

http://codex.wordpress.org/Function_Reference/wp_hash_password

$wp_hasher = new PasswordHash(16, FALSE);

$hashedPassword = wp_hash_password($password);


Other WordPress User Account Information

Regarding user information, the WordPress username, user email, as well as display name are not hashed and appear in plain text in the database.

mysql> SELECT * FROM wp_users;

+—-+————+————————————+—————+———————-+

| ID | user_login | user_pass     | user_nicename | user_email     |

+—-+————+————————————+—————+———————-+

| 1 | admin     | $P$BrYSEUIBRRoSChUYfAj55gA3HtTXC80 | admin     | joesmith@example.com |

+—-+————+————————————+—————+———————-+

1 row in set (0.00 sec)

mysql>


Salted MD5 with Iterations

The default salted MD5 hashes with 8192 iterations is perhaps the minimum security one would prefer for password hashes. MD5 is becoming more and more something to avoid if other options are available. For instance Linkedin passwords were stored in MD5 with no salt and were cracked easily within minutes. Salt and iterations significantly increases the strength and security, but unfortunately by still incorporating MD5, the current choice by the WordPress project is problematic.

Tools such as oclhashcat (http://hashcat.net/oclhashcat-plus/) are able to crack WordPress phpass MD5 hashes with salt. This can also be done with John the Ripper (http://www.openwall.com/john/). Cracking phpass MD5 hashes is so common in the cracking community that these types of hashes have become a benchmark measurement to test GPU hardware (Ex: http://www.openwall.com/lists/john-dev/2012/06/26/7). As GPU hardware becomes more and more powerful (and quickly available in large scale through cloud services), the time to crack hashes gets significantly lower.

The best course of action in using the default WordPress configuration for password hashing is to use very long passwords. Passwords 24 characters in length significantly increase the time required to attempt cracking. An absolute minimum password length recommended by this author would be 12 characters in length.

Drupal 7 has made the jump to use SHA512 with phpass along with of course salt as well as 16384 iterations. The Drupal file with all of the details is includes/password.inc (http://api.drupal.org/api/drupal/includes!password.inc/7). The long discussion on phpass implementation can be found at this thread: http://drupal.org/node/29706 . Drupal 6 and previous versions only used MD5 (no salt) for password hashes. If using Drupal 6, adopting the phpass module is an option to increase password hash strength (http://drupal.org/project/phpass/).

Conclusions

If stronger password storage requirements are required by a company or organization in regards to running WordPress, consider patching WordPress to use blowfish or DES with 16384 iterations if available on the server as shown above. If this change is not possible, consider setting a password policy requiring very long passwords for WordPress. A minimum password of 12 characters in length with 24 characters being much more secure is the recommendation of this author.

For end users browsing the web and creating user accounts on various WordPress sites, consider that the default configuration of WordPress is storing passwords in salted MD5 which can be cracked. If someone was to obtain the wp_users table of a website, not only do they have usernames and password hashes, but also an associated email address. It is critical to use unique passwords for every site so that if a site is compromised, a re-used password does not then become a personal security issue.

Hopefully future versions of WordPress will consider using stronger default algorithms for password hashing now that most all servers are running at least PHP 5.3.0. Outlining that a particular WordPress version X.x.x and later requires PHP 5.3.0 or higher for ‘password security’ will certainly be a well received gesture and is recommended to the WordPress project at this point. At any rate, using very long passwords is undoubtedly the best solution no matter what hashing algorithm is in place for a given website.