Bezpieczne haszowanie hasełHaszowanie haseł
Ta sekcja wyjaśnia powody, dla których należy używać funkcji haszujących
(skrótu) do zabezpieczania haseł, a także jak zrobić to efektywnie.
Czemu hasła podawane przez użytkowników powinny być haszowane?
Haszowanie haseł jest jedną z podstawowych metod zapewniania bezpieczeństwa, która
musi być uwzględniona na etapie projektowania aplikacji lub usługi, która przyjmuje hasła
od użytkowników. Bez haszowania dowolne przechowywane hasła mogą
mogą paść ofiarą kradzieży w wypadku naruszenia źródła danych, a
potem natychmiast użyte nie tylko do zaatakowania aplikacji lub usługi, ale także
kont użytkowników w innych usługach, jeżeli nie używają oni
unikalnych haseł.
Stosując funkcję skrótu do haseł użytkowników przed ich zapisaniem,
odgadnięcie oryginalnego hasła przez atakującego staje się niemal niewykonalne,
a my wciąż będziemy mogli porównywać wynikowy hasz do oryginalnego hasła.
Należy jednak zauważyć, że haszowanie haseł chroni jedynie przed
ich wykradnięciem z miejsca przechowywania danych, ale już nie przed
przechwyceniem przez złośliwy kod wstrzyknięty do samej aplikacji
lub usługi.
Dlaczego popularne funkcje haszujące jak md5 czy
sha1 nie nadają się do haszowania haseł?
Algorytmy haszujące takie jak MD5, SHA1 czy SHA256 zostały zaprojektowane
tak, by były bardzo szybkie i wydajne. Przy użyciu nowoczesnych technik i sprzętu,
trywialne stały się ataki typu brute force na wyniku działania tych funkcji
tak, aby odgadnąć oryginalne dane wejściowe.
Ze względu na to, jak szybko dzisiejsze komputery potrafią odwrócić te algorytmy
haszujące, wielu profesjonalistów z zakresu bezpieczeństwa nie poleca ich
stosowania do haszowania haseł.
Jak powinny być haszowane hasła, jeśli popularne funkcje skrótu nie
nadają się do tego?
Podczas haszowania haseł dwa najważniejsze aspekty to
koszt obliczeniowy oraz sól. Im bardziej kosztowny obliczeniowo
jest algorytm haszujący, tym dłużej zajmie aby poddać wynik jego działania
atakowi brute force.
PHP udostępnia
wbudowane API do haszowania haseł, które
bezpiecznie obsługuje zarówno haszowanie
oraz weryfikację haseł
w poprawny sposób.
Do haszowania haseł sugeruje się użycie algorytmu Blowfish, który
jest także domyślnym algorytmem używanym przez API do haszowania haseł, jako że
jest on zdecydowanie bardziej kosztowny obliczeniowo niż MD5 lub SHA1, a przy tym
wciąż jest skalowalny.
Do haszowania haseł może nadać się także funkcja crypt,
ale sugeruje się jej wykorzystanie tylko w celu osiągnięcia kompatybilności
z innymi systemami.
Zamiast tego zdecydowanie zaleca się użycie
wbudowanego API haszowania haseł,
gdy tylko jest to możliwe.
Czym jest sól?
Sól kryptograficzna to dane, które są stosowane podczas procesu haszowania,
aby uniemożliwić wyszukanie wyniku działania algorytmu na
listach wcześniej obliczonych par haszy i ich danych wejściowych,
znanych jako tęczowe tablice.
W prostych słowach, sól to trochę dodatkowych danych, które powodują,
że hasze stają się znacznie trudniejsze do złamania. Istnieje wiele
usług online, które posiadają rozbudowane listy wcześniej obliczonych haszy
oraz oryginalnych danych wejściowych dla tych haszy. użycie soli powoduje,
że znalezienie wynikowego hasza na takich listach jest mało prawdopodobne
lub wręcz niemożliwe.
password_hash stworzy losową sól, jeśli nie została
ona podana. Ogólnie rzecz biorąc jest to najprostsze i najbezpieczniejsze
podejście.
Jak przechowywana jest sól?
Jeśli użyta została funkcja password_hash lub
crypt, zwrócona przez nią wartość zawiera także
sól jako element wygenerowanego hasza. Ta wartość powinna być zapisana w
niezmienionej postaci w bazie danych, gdyż zawiera informacje o tym,
jaka funkcja haszująca została wykorzystana do jej stworzenia i można taką
wartość przekazać bezpośrednio do password_verify podczas
weryfikacji hasła.
Aby uniknąć ataków opartych o czas do sprawdzenia haseł powinna być
zawsze wykorzystywana funkcja password_verify,
a nie ponowne obliczenie hasza i porównanie wyników.
Poniższy diagram pokazuje format wartości zwracanej przez
crypt oraz password_hash. Jak
widać jest ona samodzielna, zawiera wszystkie informacje
na temat algorytmu oraz soli wymaganej do późniejszej weryfikacji hasła.
Elementy wartości zwracanej przez funkcje password_hash oraz crypt to
kolejno: wybrany algorytm, opcje algorytmu, wykorzystana sól
oraz zahaszowane hasło.