W BackTrack4 R2 jest plik bt4-password.txt zawierający ponad 3 miliony linii (potencjalnych haseł)...
Nudy: znowu o przechowywaniu haseł
Przy pomocy prostego skryptu w Pythonie sprawdzenie wszystkich tych haseł zajmuje w zależności od użytego algorytmu w przybliżeniu:
- MD5: 16 sekund,
- SHA1: 18 sekund,
- SHA256: 21 sekund,
- SHA512: 30 sekund,
Dodając do tego salt, wartości te wynoszą:
- SHA256: 25 sekund,
- SHA512: 33 sekundy,
Python w tym przypadku jest językiem bardzo niewydajnym, same operacje kryptograficzne to jedynie ułamek podanych czasów. Nawet w tym przypadku wyliczenie ponad 3 milionów hashy SHA512 z saltem trwa krótko, tylko dwa razy więcej niż "czyste" MD5. Zresztą takich wyników można się było spodziewać choćby po danych o wydajności w operacjach kryptograficznych podawanych przez openssl (patrz: Coś mocniejszego niż MD5).
To tak w komentarzu do kolejnego wycieku (patrz: Wpadka Mozilli – wyciek danych użytkowników serwisu z dodatkami do Firefoksa). Niespodzianka - MD5 nie jest źródłem wszelkiego ZŁA. A salt nie rozwiązuje wszystkich problemów, o czym już zresztą pisałem (ponownie patrz: Coś mocniejszego niż MD5).
Tak, przechowywanie haseł bez użycia salt jest złym pomysłem. W takim przypadku atakujący może łamać (sprawdzać) hasła w sposób bardzo efektywny, między innymi stosując rainbow tables. Akurat kwestia użytego algorytmu (funkcji skrótu) jest w tym przypadku drugorzędna. Przygotowanie tablic dla SHA512 będzie (z grubsza) dwa razy bardziej kosztowne, niż dla MD5. Nie jest to bariera nie do przejścia. Z drugiej strony długie, złożone hasło będzie praktycznie nie do złamania, niezależnie od wybranej funkcji skrótu. MD5 ma kolizje? Oczywiście, ale to wcale nie znaczy, że znalezienie ciągu danych (hasła) dającego z góry założony hash jest zadaniem trywialnym. A może jest? Jakie hasło może dać takie MD5: c28e6e726a019dc272615149b4d320f5? Dodam, że SHA1 tego hasła to 05fa4d95ecd1fa0fee02f59bbe85a132bf248e4b.
Żeby było jasne, nie twierdzę, że przy przechowywaniu hasła należy stosować MD5. Zwracam uwagę, że użycie innego algorytmu niż MD5 nie powoduje, że problemy "typowe" dla MD5 nagle przestają istnieć. Z drugiej strony przechowywanie hasła w MD5 nie implikuje tego, że każde hasło zostanie złamane (w sensownym czasie oczywiście).
Co daje salt? Jedna sprawa - salt jest jawny. Jawny w tym sensie, że musi być przechowywany razem z końcowym hashem, bo w przeciwnym razie nie będzie możliwości sprawdzenia, czy wpisane hasło jest prawidłowe. Oznacza to mniej więcej tyle, że w przypadku "wycieku" bazy haseł atakujący (najprawdopodobniej) dysponuje nie samymi hashami, ale również odpowiadającymi im saltami. Czyli proste, słownikowe hasło będzie równie łatwe do złamania w następujących przypadkach:
MD5: 8cd3bea6b7344c2920c9861e45aa7c9a SHA1: 863248e1be0e1852d4363c8fb12da101d852e112 SHA1(salt+password): 796d948b8e45c53c49ef43ad940ba068 6a3a2a06061e92a294b4e41dd759b159f664dcc4
Te powyższe hashe każdy sobie może spróbować połamać...
Salt daje głównie dwie korzyści:
- nawet jeśli użytkownicy mają takie same hasła, ich hashe są różne, bo różne są salty,
- (w praktyce) nie można stosować rainbow tables,
Dodatkowo jeśli dysponuje się hashami haseł dla n użytkowników konieczne jest n-krotne sprawdzenie danego hasła (słownikowe, brute force), przecież każdy z hashy został wyliczony z użyciem innego salta. Czy jest to istotna różnica? Zależy. Jeśli łamanych jest kilkaset lub kilka tysięcy haseł - tak. Jeśli jednak obiektem ataku jest jedno lub kilka haseł, atak słownikowy czy atak brute force nie jest dużo bardziej kosztowny, niż atak na hashe haseł wygenerowane bez użycia soli.
Użycie soli nie gwarantuje, że hasło będzie nie do złamania. Słabe, słownikowe hasła nadal daje się łamać w sensownym czasie. Sensownym, czyli takim, w którym atakujący może ze złamanego hasła mieć jakąś korzyść.
Hasła powinny być hashowane przy pomocy algorytmu, który został specjalnie w tym celu zaprojektowany, i który jest kosztowny obliczeniowo. Oczywiście nawet wówczas łamanie hashy nadal będzie możliwe, koszt (obliczeniowy) takiego zadania będzie jednak zdecydowanie większy, niż ten, który uda się osiągnąć stosując SHA512 i absurdalnej długości salt.
Po co o tym (znowu) piszę? Bo być może po kolejnych informacjach na temat wycieku haseł przechowywanych z użyciem MD5 ktoś zabierze się do roboty i zdecyduje się na wprowadzenie zmian... Niech to już zrobi porządnie.
Sprawa druga: ile to "sensowny" czas?
Sensowny czas to taki, który jeszcze pozwala na użycie złamanego hasła. W sumie to zależy od tego, czego hasło chroni. Jeśli są to super tajne dokumenty, które mają być ujawnione po 50 latach, to sensowny czas jest mniejszy od 50 lat
Ale cóż, w szkolę tego nie uczą, w książkach o programowaniu też w sumie nie, skąd niby typowy programmers ma wiedzieć ? Jemu płacą za ficzery nie za security ;]
Druga sprawa - przecież czas łamania można skrócić dokładając kolejne maszyny pracujące nad tym samym zadaniem. Operowanie na jednostce "połowa czasu łamania" jest ryzykowne, w końcu wystarczy dołożyć drugie tyle zasobów (no dobra, trochę więcej, nie skaluje się to liniowo) i pozamiatane.
Ja uważam, że dobre rozwiązanie to przede wszystkim unikalne hasło dla każdego serwisu. Nie trzeba go pamiętać, od czego są rozwiązania typu KeePass. W takim przypadku nawet jeśli z jakiegoś serwisu wyciekną hasła i atakujący je złamią (mało prawdopodobne przy losowym, długim haśle generowanym automatycznie), to i tak nie wykorzystają go w innym serwisie.
Pytanie, jaką maszynę(-y) przyjąć u łamiącego, ale wydaje mi się, że "najmocniejsza pojedyncza" jest dobrym przybliżeniem. Zrównoleglanie nie jest tak drastycznym problemem. Dodatkowe dwa znaki (zakres poniżej) w haśle to prawie 4 tys. maszyn potrzebnych do jego łamania w tym samym czasie. Trochę sporo, nawet licząc koszt samej energii elektrycznej, chociaż oczywiście zależy, co to za dane.
Dla [a-zA-Z0-9] i 8 znaków mamy 62^8 kombinacji. Przy MD5 sprawdzanych jest obecnie jakoś 33 mld/s na pojedynczej maszynie, co oznacza, że "czas bezpiecznego życia" takiego hasła to... godzina. Zdecydowanie się nie nadaje.
10 znaków to - jeśli nie pomyliłem się w obliczeniach - niecałe pół roku. Czyli 11 znaków (dla spokoju wypada dorzucić jeszcze 2 znaki przeciw zrównoleglaniu) to obecnie minimum, jeśli ktoś chce zmieniać hasło raz na rok. No i szacowanie zmian szybkości łamania przy pomocy prawa Moore'a (hmm, właśnie, fajne byłoby sprawdzenie, czy prędkość łamania też podlega temu prawu...).
Duża litera i cyfra - cóż, taka natura userów.
KeePass - fajne (bardzo fajne), ale... Dla większości użytkowników odpalanie programu przed każdym zalogowaniem do każdego serwisu jest nieakceptowalne. Plus, są przywiązani do maszyn/sprzętu, co też niekoniecznie jest akceptowalne.
Tak trochę przez analogię - hash NTLM to MD4 na haśle (po drobnych przekształceniach). Tu można zobaczyć jakie tablice (te dla Visty, bo te dla XP opierają się o LM) są dostępne: http://ophcrack.sourceforge.net/tables.php
Jeśli chodzi o moc obliczeniową, to bym nie przesadzał tak bardzo z jej niedostępnością:
- botnety,
- chmura (cudza),
Patrząc z perspektywy "normalnego ludzia" 4 000 komputerów to może i dużo, ale z drugiej strony ile komputerów jest elementem botnetu? Albo ile osób atakowało te złe firmy utrudniające życie WikiLeaks?
Chmura kosztuje, botnet kosztuje (choćby utracone korzyści). Poza tym, przeciętna maszyna w botnecie to raczej nie 4 x dual core GPU.
Ale OK, przekonałeś mnie do kolejnego znaku. Nawet dwóch.