43
var_dump(md5('240610708') == md5('QNKCDZO'));

Output:

bool(true)

Example: http://3v4l.org/2vrMi

Farid Movsumov
  • 12,350
  • 8
  • 71
  • 97
  • 3
    use "===" and you get `false` –  Mar 03 '14 at 06:39
  • 2
    They are not the same (php is probably converting them to integers and doing integer comparison → use `===` instead) – knittl Mar 03 '14 at 06:39
  • 1
    I can't answer here, but it seems like your both parts has `0^(x)`, where `x` is next part of hash. This way, `0e123` is intepretating as int: `0^123`. So, `0^y==0^x` for any `x,y>0`. So, you got output `true` – Egor Apr 27 '19 at 12:44

2 Answers2

65

md5('240610708') 's result is 0e462097431906509019562988736854.

md5('QNKCDZO') 's result is 0e830400451993494058024219903391.

They are both float number format strings (numerical strings), and if you use == in php, when compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically.

Both of the strings are converted to 0 when compared with ==, if you want to compare them as string, remember to use ===(strict comparison) instead.

See: PHP expresses two different strings to be the same

Community
  • 1
  • 1
xdazz
  • 158,678
  • 38
  • 247
  • 274
  • 5
    Hashes should also, in a lot of cases, also be compared in constant-time (especially in the context of a MAC to authenticate a ciphertext). So the == bug isn't critical, since you should never be using == for security-sensitive hash comparisons. – Scott Arciszewski Mar 07 '14 at 13:54
  • @ScottArciszewski really? What does it really give the attacker to learn the size of the prefix of a constant pseudorandom string A with a pseudorandom string B? – Niklas B. Feb 21 '16 at 23:19
  • If you know M and HMAC(M, K), and you want to find a valid HMAC(M', K) for M', you can send your M' and use timing information to build a valid HMAC output without needing to ever know K. – Scott Arciszewski Feb 22 '16 at 02:05
  • 3
    There is a good article about this security vulnerability and it also explains how to bypass strcmp by using an array: https://marcosvalle.github.io/ctf/php/2016/05/12/php-comparison-vlun.html – baptx Nov 05 '18 at 19:05
18

You need to use the type-sensitive comparison operator ===.

The hashes evaluate to 0e462097431906509019562988736854 and 0e830400451993494058024219903391, respectively. When you use ==, each is converted to a numeric representation because of the e (scientific notation), so they each become 0. 0 == 0 is true.

On the other hand, this:

md5('240610708') === md5('QNKCDZO')

returns false because the string values are different. === forces type-sensitive comparison.

elixenide
  • 44,308
  • 16
  • 74
  • 100