Dlaczego k-anonimowość nie jest dobra przy hasłach?

Na z3s.pl pojawił się artykuł o tym, czym jest k-anonimowość. Jest to dobry artykuł i warto go przeczytać przed lekturą tego wpisu. Nie zgadzam się jedynie z tezą, że w przypadku haseł jest to bezpieczna metoda sprawdzania. Napisałem komentarz, ale pewnie nie wszyscy czytelnicy bloga tam trafią. Ponieważ bawię się z bazą hashy z HIBP i planuję wkrótce wpis na ten temat, uznałem, że jest dobra okazja do wstępu.

Moja teza jest taka, że w przypadku haseł k-anonimowość wcale nie jest taka bezpieczna, jak jest to przedstawiane. Zgodnie z artykułem obecnie dla hashy z bazy HIBP pierwsze 5 znaków występuje od 381 do 584. Czyli podczas sprawdzenia strona trzecia nie poznaje ani hasła, ani jego pełnego hasha. Przekazywane jest jedynie pierwszych 5 znaków hasha, czyli – tu moja interpretacja – ma jedynie 1/381 do 1/584 prawdopodobieństwo, że zna właściwy hash.

Gdyby przyjąć, że strona trzecia jest złośliwa, warto też przyjąć, że jest inteligentna. Czyli zamiast prawdopodobieństwa zwykłego użyje prawdopodobieństwa ważonego, uwzględniając ilość wystąpień danego hasha. Dla przykładu z artykułu na z3s.pl i hasła P@ssw0rd mamy zwracanych 543 różnych hashy:

curl -s https://api.pwnedpasswords.com/range/21BD1 | wc -l

Natomiast suma wystąpień wszystkich hashy w momencie pisania tego wpisu wynosi 60808.

curl -s https://api.pwnedpasswords.com/range/21BD1 | awk -F ":" '{sum += $2} END {print sum}'

Nasz hash wystąpił 52579 razy. Znając zwyczaje ludzi dotyczące haseł i stosując prawdopodobieństwo ważone uzyskujemy 86% szansę na to, że chodzi o hash należący do hasła P@ssw0rd. Pewności nie ma, ale z 1/543 czyli z ~0,18% robi się 86%, czyli jakieś 467 razy więcej. Ups!

Oczywiście nie znamy tu samego hasła. Znamy jedynie – a i to jedynie ze sporym prawdopodobieństwem – jego hash. O tym, że to niekoniecznie jest problem, może będzie w którymś kolejnym wpisie.

W każdym razie gdybym był serwisem, to bałbym się odpytywać serwis trzeci o hashe haseł moich użytkowników. Użytkowników podejrzewam o proste, słownikowe hasła, jakiś serwis trzeci. Zwłaszcza jeśli ten serwis ma/może mieć także inne informacje, które pozwalają mu ustalić kto pyta o hasło. Tak właśnie może być w przypadku Cloudflare, który może dostawać część ruchu od użytkownika w ramach CDN, DNS lub DoH. Prosta korelacja czasowa może w tym przypadku prowadzić do powiązania hasha hasła z IP użytkownika. Jeśli chcemy sprawdzać hasła, to lepszym rozwiązaniem jest stworzenie lokalnej kopii bazy którą pobierzemy z HIBP.

Co nie znaczy oczywiście, że k-anonimowość ogólnie nie spełnia swojego zadania. Po prostu mam wrażenie, że akurat w przypadku hashy hasła i tej konkretnej implementacji nie jest tak bezpieczna, jak jest to przedstawiane.

Warto też zauważyć, że hasło z którym mamy tu do czynienia jest proste/populare. Dla innych pięcioznakowych początków hashy wystąpienia mogą rozkładać się inaczej, bez tak silnego wskazania na konkretny hash.

UPDATE Tak naprawdę nie ma potrzeby używania całej bazy hashy i ilości ich wystąpień z HIBP (>20GB). Najczęściej występujące 100 tys. hashy to raptem 3,2 MB. Najczęstszy milion – 32 MB.

Łamanie hashy NTLMv2 na podstawie pcap

Tu jest oryginalny wpis o jak crackować hash NTLMv2 pobierany z pliku pcap, wszystko opisane ładnie i dokładnie, ze zrzutami ekranu, ale pozwolę sobie na skrócony mirror, bo przydaje mi się to sporadycznie, a sądząc po kondycji strony z oryginałem niewykluczone, że do tego czasu oryginalny wpis zniknie (obym się mylił).

  1. Filtr ntlmssp w wireshark.
  2. Potrzebne dane w formacie dla hashcata, zapisywane w crackme.txt:
    username::domain:ServerChallenge:NTProofstring:ntlmv2response
  3. Oryginalne ntlmv2response zawiera na swoim początku NTProofstring, należy go usunąć przed użyciem wyżej.
  4. Uruchomienie:
    hashcat -m 5600 crackme.txt passwordlist.txt

Jak widać ekstrakcja hashy NTLMv2 potrzebnych danych ze zrzutu ruchu sieciowego jest ręczna. Szukałem pobieżnie automatu, ale nie znalazłem, a skoro używam rzadko, to pisać nie ma sensu. W sumie nie tyle pisać, co próbować pisać, bo rozmieszczenie danych miałem nieco inne, niż w linkowanym przykładzie. Gdyby jednak ktoś znał coś takiego, to chętnie poznam.

Przyspieszyć hashcata

Na blogu nfsec.pl pojawił się wczoraj wpis dotyczący crackowania hashy md5crypt[1] przy pomocy hashcat. Spojrzałem na sprzęt i moją uwagę przykuła wydajność karty Intela Intel(R) Iris(TM) Graphics 650:

Hashmode: 500 - md5crypt, MD5 (Unix), Cisco-IOS $1$ (MD5) (Iterations: 1000)
Speed.#2.........: 423.2 kH/s (53.30ms) @ Accel:256 Loops:250 Thr:8 Vec:1

Mam Intel Corporation Skylake GT2 [HD Graphics 520] widzianą jako Intel(R) Gen9 HD Graphics NEO i hashcata w wersji v5.1.0 (binarka, stable), na potrzeby zabaw z platformami CTF, o których wspominałem niedawno. Część zadań wymaga użycia brute force. Chociaż nie było do tej pory okazji wyjść poza coś typu gotowy słownik, to pewnie jeszcze się przyda. Rzecz w tym, że moja karta jest znacznie wolniejsza:

Hashmode: 500 - md5crypt, MD5 (Unix), Cisco-IOS $1$ (MD5) (Iterations: 1000)
Speed.#1………: 156.1 kH/s (76.04ms) @ Accel:256 Loops:250 Thr:8 Vec:4

Rozumiem, że to inny sprzęt i inny system (u mnie Debian w wersji unstable), ale postanowiłem podrążyć temat.

Po pierwsze, zauważyłem, że mam starsze pakiety OpenCL dla Intela. Aktualizacja nie przyniosła co prawda poprawy wydajności, ale na innym sprzęcie (Ubuntu) była w ogóle niezbędna do poprawnego działania hashcata. Bez najnowszej wersji md5crypt w ogóle nie dawał się tam łamać.

Po drugie, hashcat, którego użyłem w wersji z GitHub (wersja development) to v5.1.0-951-g6caa7869 (również niezbędny na Ubuntu do poprawnego łamania md5crypt). Efekt okazał się całkiem przyjemny:

Hashmode: 500 - md5crypt, MD5 (Unix), Cisco-IOS $1$ (MD5) (Iterations: 1000)
Speed.#1………: 232.7 kH/s (51.57ms) @ Accel:256 Loops:250 Thr:8 Vec:4

Niemal połowę szybciej. Warto aktualizować soft i sterowniki, nawet, jeśli wersja wygląda na tylko nieznacznie nowszą. Co ciekawe, przyrost wydajności jest tak duży tylko dla niektórych algorytmów, w tym md5crypt. Inne, jak zwykłe md5 różnice mają jedynie symboliczne:

Hashmode: 0 - MD5
Speed.#1………: 476.6 MH/s (51.75ms) @ Accel:128 Loops:32 Thr:256 Vec:4

Hashmode: 0 - MD5
Speed.#1………: 493.4 MH/s (50.09ms) @ Accel:512 Loops:128 Thr:16 Vec:4

Tyle tym razem – trochę o instalacji i uruchomieniu hashcata, trochę o przyspieszeniu na poziomie softu. Mam świadomość, że to trochę takie wyścigi ślimaków, ale… jak się nie ma co się lubi, to się lubi co się ma. Może kiedy indziej będzie o doborze parametrów i budowie skutecznych słowników do crackowania hashy przy pomocy hashcata.

[1] Ładnie po polsku, owinięte w bawełnę, nazywa się to audyt haseł. Ewentualnie, mniej owijając w bawełnę, łamanie funkcji skrótu haseł. Zostanę jednak przy brzydkiej, potocznej wersji angielskiej.