Dlaczego nie powinieneś używać podwójnego znaku równości (==) porównując hashe w PHP

Dlaczego nie powinieneś używać podwójnego znaku równości (==) porównując hashe w PHP

Dzisiaj poruszymy temat pewnej podatności w języku PHP, która została opisana na
Twiterze Michala Špačeka już jakiś czas temu.

Artykuł dostępny także w wersji angielskiej.

Mianowicie, zauważył on, że w języku PHP następujące porównanie zwraca wartość true

W pierwszej chwili można by się tutaj doszukiwać wystąpienia kolizji funkcji skrótu dla dwóch różnych wartości. Jednak jeśli wyświetlimy poszczególne z tych wartości otrzymamy następujący wynik:

Dlaczego zatem powyższe porównanie zwraca wartość true? Okazuje się, że obie z tych wartości zawierają same cyfry poza wartością występującą na drugim miejscu, która jest literą e.
Wszyscy wiemy zapewne, że wiele wartości matematycznych zapisywanych jest w postaci, przykładowo:
2*10^{20}
Co właśnie można również ująć jako:
2e20

Przyglądając się bliżej wynikom naszej funkcji hashującej możemy zauważyć, że wartości te to dokładnie taki właśnie zapis wartości pewnej liczby. W takim przypadku język PHP traktuje tę wartość jako liczbę. Oblicza jej wartość, a następnie porównuje.

Wartość 0e462097431906509019562988736854 zatem w zapisie matematyczny można zapisać jako:
0*10^{462097431906509019562988736854}

Podobnie 0e830400451993494058024219903391 to:
0*10^{830400451993494058024219903391}

Ponieważ pierwsza liczba to 0 więc oba wyrażenia przyjmą ostatecznie wartość zero więc całe porównanie zwróci oczywiści true. Podobnie wyrażenie zachowa się jeśli pierwsze znaki wyniku funkcji hashującej będą miały wartość 1.

Aby się ustrzec przed takim niespodziewanym działaniem należy albo używać porównania przy pomocy potrójnego znaku = (===) albo skorzystać z wbudowanej w PHP funkcji hash_equals().

Należy pamiętać, że opisywana podatność wystąpi również w przypadku innych funkcji hashujących jak na przykład SHA. Jeśli jej wynikiem będzie wartość zawierająca same cyfry (poza drugą pozycją), na drugim miejscu będzie litera e, a pierwsza cyfra będzie równa 1 lub 0 to problem ten także wystąpi. Warto o tym pamiętać i odpowiednio się przed tym zabezpieczyć.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *