Ile kosztuje hasło na Raspberry Pi
Strony statystyk można tu chronić hasłem. Zahaszowanie tego hasła to jedyna operacja w tym serwisie, która ma być powolna — właśnie to sprawia, że skradziony skrót jest drogi w ataku. Pytanie brzmi: jak powolna, na tym sprzęcie.
Zmierzone na maszynie, która prowadzi tę stronę, PHP 8.4.21 na aarch64:
PASSWORD_DEFAULT | 560 ms | (daje cost 12) |
| cost 12 | 595 ms | |
| cost 11 | 277 ms | |
| cost 10 | 138 ms |
Parametr kosztu w bcrypt jest wykładnikiem: każdy stopień podwaja pracę. Pomiary pokazują dokładnie to podwojenie, co jest dobrym znakiem, że nic innego się nie wtrąca.
Dlaczego wartość domyślna jest tu złym wyborem
PHP podniosło domyślny koszt bcrypt z 10 na 12. Na serwerze w centrum danych to rozsądne podniesienie — kilkadziesiąt milisekund. Na małej płytce ARM to ponad pół sekundy czystego procesora, na maszynie, która w tym samym czasie rysuje obrazki liczników dla wszystkich innych.
Pół sekundy na jedno logowanie jest złe samo w sobie. Gorsze jest jako zaproszenie: punkt logowania może wywołać każdy, a każde wywołanie zjada 560 ms jedynego procesora obsługującego całą stronę. To czyni sprawdzanie hasła najtańszym sposobem przeciążenia, jaki tu jest.
Koszt jest więc przybity do 10, a nie zostawiony wartości domyślnej. To celowo słabiej niż to, co PHP wybiera dzisiaj, i trzeba to powiedzieć wprost, a nie zakopać: skrót o koszcie 10 jest cztery razy tańszy w ataku niż o koszcie 12. Odkupuje to jedno — to, czego hasło naprawdę broni: widoczności strony z liczbami odwiedzin, nie konta, nie pieniędzy, nie tożsamości. Za tym nie ma nic, co dałoby się przejąć.
Część, którą łatwo przeoczyć
PASSWORD_DEFAULT jest z założenia wartością ruchomą. Stary kod, który jej używa, będzie po cichu wolniejszy z każdą aktualizacją PHP — to samo źródło, to samo wejście, wielokrotność czasu wykonania. Tak ma być i dla większości oprogramowania jest to słuszne.
Złe jest tylko wtedy, gdy maszyna tego nie udźwignie, a nic nie ostrzega, kiedy nie udźwignie. Aktualizacja się udaje, testy przechodzą, strona nadal działa. Po prostu trwa o pół sekundy dłużej, a na tę liczbę nikt nie patrzy, jeśli nie pójdzie i nie zmierzy.