ISPA Winner 2018 17 years of Krystal

PHP hash comparison bug – red alert?

Steve Sant

By: Steve Sant in Administration

Posted on: May 11th 2015 at 13:30pm

A couple of days ago WhiteHat Security’s Robert Hansen, aka RSnake, accounced a PHP ‘Magic Hash’ vulnerability. In essence, it is common practice to hash user passwords using MD5 or SHA1, possibly mixing them up with salt values before storing them in a database for later use.

That’s all fine and dandy, but PHP apparently has a rather nasty bug/feature whereby any string tested using the == or != operators, where the string begins with 0e (the scientific notation for zero to the power of something) will give the same result as testing zero.

This provides a way to compromise any user account whose password when hashed gets equated to zero by PHP. If any passwords in the database are stored with hashes that also start with 0e then an attacker will gain access.

Hansen said the problem has been around for a year, but nobody has gone out of their way to find any magic passwords that produce unsalted hashes beginning with oe. Until now…

In a github project, posted to Hansen’s twitter feed are listed several “magic” numbers found to produce hashes that are treated as zero by PHP.

Hansen estimates the chances of a 32-character hash starting with 0e in in the order of 1 in 200 million. That might not seem much, but there are an awful lot of passwords out there!

Addressing the problem is simple. Developers should look for PHP code used to test hashed passwords and change == or != and change them to === or !== respectively.

PHP’s == operator compares the values of variables for equality, while automatically type casting as necessary – and this is where the problem occurs. === on the other hand, checks if the two variables are of the same type AND have the same value, thus treating 0e as a strong, and not as a number that begins with an scientifically notated exponent.

The PHP password_verify() function was probably never in danger, plus it uses only Bcrypt or Blowfish and I’m not aware of any published rainbow tables for the output from this PHP function.

Another mitigating factor would be that if any salt value was used, then the lists of unsalted magic hash values provided in the github list above would not work.

So, a very real vaulnerabilty, easy to execute, but one for which ir is extremely, incredibly, hard to find a vulnerable target.