This week the Roots development team released wp-password-bcrypt, a plugin that uses bcrypt instead of MD5 password hashing. MD5’s known and exploited weaknesses have rendered it “cryptographically broken and unsuitable for further use,” according to the CMU Software Engineering Institute.
In a post announcing the plugin, Scott Walkinshaw explained why WordPress’ default MD5 hashing function + salting is insecure:
MD5 is considered “broken” due to its collision vulnerability, but it’s broken more fundamentally for passwords: it’s too cheap and fast to calculate a hash.
bcrypt, on the other hand, is much slower than MD5, making it more expensive to calculate. This stronger method of password hashing is built into PHP 5.5, but WordPress maintains 5.2.4 as its minimum required version. This precludes WordPress from using the newer password_hash function.
Walkinshaw cites a four year old ticket which proposes a way for WordPress to allow plugin developers to more easily change from the salted MD5 method of hashing to the more secure bcrypt. James McKay left a sobering comment on that ticket, advocating that WordPress core move to make bcrypt the default for environments that support it:
bcrypt needs to be made the default, out of the box option on all systems that support it. The idea that WordPress admins should have to go hunting for a plugin or tweak configuration options to do this scares me, simply because most of them won’t unless (a) they are well versed in web security, (b) they know that WordPress uses a weak alternative by default, and (c) they consider it to be an issue worth worrying about.
People often underestimate the seriousness of MD5 and the SHA-* algorithms being “less secure.” They aren’t just less secure: thanks to developments in password cracking in the past few years using GPU- and FPGA- based software, they are totally useless. Programs such as oclHashCat even have an option specifically to crack passwords in WordPress databases — and the rate at which they can do so is terrifying. If you’re not making a strong password hashing algorithm the default, out of the box option, you’re exposing your users to unacceptable and unnecessary risk.
Unfortunately, action on the ticket has been held up due to a UX issue. Discussion on the ticket continues, but contributors have not yet settled on a path for improvement.
“So what is holding up the switch?” Walkinshaw said. “Bureaucracy and the unwillingness to make it happen. The consensus of the ticket is that it’s actually a UX problem. At this point, there is no technical reason why this can’t be done.”
In the meantime, if you want to implement secure bcrypt hashed passwords, you can use the wp-password-bcrypt plugin from the Roots team. It will protect against database compromises. If your WP database fell into the wrong hands, attackers would have a much more difficult time attempting to brute force a bcrypted password versus a MD5-based password.
The plugin re-hashes user passwords with bcrypt when users log in. If a user never logs in, the password remains hashed with MD5. It can also be uninstalled without negative consequences. There are no settings – it simply works in the background.
“We’ve purposely tried to keep the plugin as simple as possible so there are no surprises,” Walkinshaw said. “Obviously we recommend people test out the plugin first, and hopefully put it on a staging site first.”
The plugin can be installed by automatically autoloading it with Composer or by manually copying wp-password-bcrypt.php into your mu-plugins folder. It will also soon be added to Roots’ Bedrock project boilerplate to provide a more secure default.