Ein schon ein etwas älteres Phänomen, welches mir demletzt erneut über den Weg gelaufen ist und ich es deswegen für „verbloggenswert“ halte:
if (md5('240610708') == md5('QNKCDZO')) { echo "yep equal"; }
Ups? Eine MD5-Kollision? Nein. Eine Eigenart von PHP.
var_dump(md5('240610708')); //string(32) "0e462097431906509019562988736854" var_dump(md5('QNKCDZO')); //string(32) "0e830400451993494058024219903391"
2 verschiedene Strings, die aber laut PHP-Vergleich identisch sein sollen? Genau da liegt der Knackpunkt: Die Strings sind gleich, aber nicht identisch. Da beide mit 0e anfangen, werden sie als Exponentialdarstellung einer Zahl aufgefasst. Und da 0irgendwas immer 0 ergibt, sind die beiden Hashes im Vergleich auch gleich.
Das „Problem“ lässt sich einfach lösen, indem mit === verglichen wird. Dann evaluiert PHP den Zahlenwert des Strings nicht mehr. Oder indem strcmp verwendet wird:
var_dump(strcmp(md5('240610708'), md5('QNKCDZO'))); //int(-1)
SHA und Konsorten sind für diese Problematik genau so anfällig, es ist nur entsprechend unwahrscheinlicher, dass es zu solch einem „0e“-Phänomen kommt. In der Praxis hätten Angreifer also eine bessere Chance, wenn zu „0e“ evaluierende Hashes beim Bruteforcen vorrangig probiert werden. Aber auch dann ist der Angriff selbstverständlich von der Nachlässigkeit des Entwicklers abhängig: Sobald mit === verglichen wird (bzw. ein „ordentliches“ Hash-Verfahren wie bcrypt mit Salt verwendet wird) sieht es düsterer aus.
„demletzt“ – hach herrlich. :) Ist aber ein echt interessantes Thema. Viele Grüße nach Darmstadt!