Today we will say about some susceptibility in PHP language, which has been described on Michala Špačeka’s Twitter some time ago.

Article is also available in Polish version.

Namely, he noted that in the PHP language the following comparison returns a *true* value

1 |
var_dump(md5('240610708') == md5('QNKCDZO')); //true |

At the first moment, it would look like a collision occurrence of a shortcut function for two different values. However, if we display each of these values, we get the following result:

1 2 |
var_dump(md5('240610708')); //0e462097431906509019562988736854 var_dump(md5('QNKCDZO')); //0e830400451993494058024219903391 |

So why does the above comparison return *true? It turns out that both of these values contain the digits except second sign, which is the letter e.*

We all probably know that many mathematical values are written in this way:

2*10^{20}

What we can write down such:

2e20

Taking a closer look at the results of our hash function, we can see that these values are exactly the same as mathematical representation of some number. In this case, PHP treats this value as a number. It calculates its value and then compares it with another one.

So we can write 0e462097431906509019562988736854 value in mathematical representation as:

0*10^{462097431906509019562988736854}

Similar, value 0e830400451993494058024219903391 is equal:

0*10^{830400451993494058024219903391}

Because the first number is 0, both expressions will return value zero, so the entire comparison will of course return *true*. Likewise, if the first number of result of hash function will be equal 1, this expression will behave in the same way.

To avoid such unexpected behavior, it’s important to use either compare using the triple = (===) or use the built-in PHP function such hash_equals().

Note that this vulnerability will also occur for other hash functions, such as SHA. If its result will be value containing only numbers (except for the second position), and *e* will be at the second place, and the first digit will be 1 or 0 the problem will also occur. It is worth remembering and adequately protect yourself from this.