Aplikacje internetowe

Bełdziowe spojrzenie na aplikacje internetowe

Bezpieczeństwo funkcji hashujących

Wstęp

Zadaniem funkcji skrótu (hashujących) jest wygenerowanie krótkiego ciągu znaków (skrótu / hashu) z danych wejściowych. Przykładem użycia może być wygenerowanie 32 znakowego (MD5) skrótu dla pliku, którego rozmiar to 2 GB. Umożliwia to weryfikację poprawności pliku np. po pobraniu go z Internetu możemy porównać hashe, by dowiedzieć się, czy został pobrany poprawnie.

Inne zastosowanie funkcji hashujących, możemy spotkać w większości stron internetowych posiadających użytkowników – jest to tworzenie skrótów ich haseł. Wykorzystywana jest tutaj jedna z właściwości funkcji hashujących tzn. jednokierunkowość. Oznacza to, że nie można odtworzyć działania funkcji tzn. mając hash hasła nie możemy odzyskać go w jawnej formie. Ale czy daje nam to 100% bezpieczeństwa?

Niebezpieczeństwo

Mimo, że funkcje skrótu są jednokierunkowe nadal grozi im niebezpieczeństwo ataku siłowego oraz słownikowego. Jednak ze względu na nikłe możliwości ochrony przed nimi (np. system banowania za zbyt dużą liczbę niepoprawnych logowań) oraz na wymagane zasoby ataki te możemy pominąć. Do niedawna korzystanie z hashy było uznawane za bardzo bezpieczne aż do momentu stworzenia tęczowych tablic (ang. rainbow tables).

Tęczowe tablice są poważnym zagrożeniem dla funkcji skrótu. Mają dwie cechy, które świadczą o ich możliwościach – szybkość i niezawodność – a do tego nie wymagają dużych zasobów. Jedynym wymogiem skutecznej pracy tęczowych tablic jest posiadanie odpowiedniego programu oraz plików ze skrótami.

Mogłoby się wydawać, że skoro potrzebne są pliki ze skrótami atak ten nie różni się niczym od ataku słownikowego. Tak jednak nie jest. Pliki ze skrótami mimo, że również zajmują sporo miejsca nie są aż tak duże jak te wymagane w ataku słownikowym. Zmniejszenie wielkości słownika uzyskano poprzez ograniczoną ilość zapisanych hashy, mimo czego skuteczność nie spada. Z mniejszym rozmiarów plików wzrasta również szybkość łamania skrótów.

Jak się bronić?

Najczęściej używanym i rozpowszechnianym zestawem tablic są te umożliwiające łamanie haseł utworzonych z liczb, liter oraz podstawowych znaków o maksymalnej długości 8 znaków. Fakt ten można wykorzystać podczas tworzenia systemu zarządzania hasłami. Przykładowe kody zabezpieczające hasła przed opisaną wyżej tablicą:

<?php
  $passwd = $_GET['passwd'];
  $length = 9 - strlen( $passwd );    // obliczenie ilości potrzebnych znaków
  $dots = str_repeat( '.', $length ); // wygenerowanie potrzebnych znaków
  echo md5( $passwd . $dots );      // wygenerowanie hasha
?>
Listing 1. Zagwarantowanie by hasło miało minimalnie 9 znaków.
<?php
  $passwd = $_GET['passwd'];
  echo md5( $passwd . "\n" );
?>
Listing 2. Dodanie znaku niewystępującego w tablicach.

Najlepszym sposobem zabezpieczenia się przez tęczowymi tablicami jest użycie sposobu znanego z systemów z rodziny *NIXów czyli dodania do haseł soli. Sól jest losowym ciągiem znaków stanowczo podnoszącym bezpieczeństwo generowanych skrótów. Sposób tworzenia soli zależy tylko od wyobraźni programisty piszącego system zarządzania hasłami, można np. użyć do tego funkcji microtime, rand, md5, sha1 etc.

<?php
  $passwd = $_GET['passwd'];
  $salt = microtime( );
  echo md5( $passwd . $salt );
  // zapisanie soli
?>
Listing 3. Dodanie soli do hashowanego hasła.

Hashe po stronie klienta.

Wdrożenie zabezpieczenie przed tęczowymi tablicami jest szczególnie ważne w przypadku trzymania danych po stronie klienta np. w ciastkach. Przykładowo strona IdzDoKina.pl stworzona przez Multikino trzyma w ukrytym polu czas ukończenia gry. Dzięki tęczowym tablicom możliwe jest odczytanie tej wartości i zmianę jej tak, aby osiągnięty przez nas czas był jak najniższy.

Podsumowanie

Tęczowe tablice poważnie zachwiały bezpieczeństwem funkcji skrótu. Mimo tego nadal możemy z nich korzystać w celu zapewnienia bezpieczeństwa przechowywanych haseł. Jedyne o czym należy pamiętać to dodawanie do haseł losowego ciągu znaków uniemożliwiające dostęp do jawnej postaci haseł.

Warto zajrzeć


Tagi: , , , , , , , ,
Kategoria: Bezpieczeństwo, Bezpieczeństwo aplikacji internetowych


28 komentarzy

  1. krwawyjepetto napisał(a):

    Brawo wcześniej o tym nie słyszałem :D

  2. Ktos napisał(a):

    „Soli”? Ja słyszałem zawsze o losowym „ziarnie”, podobnie jak „ziarnie” przy generowaniu liczb pseudolosowych. Aczkolwiek na Wiki też jest „salt”, a nie „seed”.

    Warto też dodać, że przykładowo SHA-1 doczekało się wykrycia kolizji już przy stosunkowo niedużych wartościach, dlatego o wiele lepiej jest stosować MD5 lub dłuższe wariantu SHA-2 (SHA-256, SHA-512). MD4 i MD5 też bezpieczne nie są (do znalezienia kolizji w MD5 wystarczyła godzina pracy klastra komputerów w 2004 ;-)), ale jeżeli sól/ziarno są często zmieniane, to bez komputerów kwantowych póki co są bezpieczne.

  3. Michał `Bełdzio` Ławicki napisał(a):

    @Ktosiu też zawsze mówiłem ziarno :-) ale wszędzie gdzie mówi się o rainbow tables wszyscy wspominają o soli, a nie o ziarnie :-) W każdym bądź razie chodzi o losowy ciąg znaków :-)

  4. pedros napisał(a):

    Przyznaj beldzio przez kogo ten art ;)

    1.
    $passwd = $_GET[”passwd”];
    $salt = microtime( );
    echo md5( $passwd . $salt );

    Wez teraz zweryfikuj czy przy nastepnym logowaniu podano poprawne haslo? Bedziesz zapisywal sobie ten microtime()? :>

    2.
    Przydaloby sie wspomniec ze teczowe tablice mozna sobie samemu wygenerowac, i wcale nie musza ograniczac sie do 8znakow, po prostu te z 8znakami sa wygenerowane i kraza po sieci. Jak ktos bedzie mial chcice (i odpowiednio duzo wolnego czasu procesora i miejsca na dysku) moze miec i 20znakowe ;)

    3.
    Mogles napisac przykladowe rozmiary tablic, bo ludzie ktorzy nie wiedza o co lotto pewnie juz zacieraja rece do sciagania, a tu zonk jak sie dowiedza ze aby miec w miare przyjemny pakiet do lamania md5 nalezy zarezerwowac 70GB ;) A to tylko MD5

    4.
    Wypadalo napisac o programie rainbowcrack (od niego to chyba wszystko sie zaczelo) Ma on ta przewage nad Ophcrack ze jest dostepny pod linuksa i mozna go odpalac na konsoli ;)

    Tak to tyle co mi sie w oczy rzucilo :>

  5. Michał `Bełdzio` Ławicki napisał(a):

    @pedros:

    ad1. w kodzie masz zakomentowane " // zapisanie soli" czyli zapisujemy sól wraz z hashem

    ad2. pewnie, że można :) jednak trwa to na tyle długo, że lepiej pobrać gotowe :)

    ad3. ok :) tak więc przykładowe rozmiary tablić można znaleźć tu -> http://www.freerainbowtables.com/index-rainbowtables-tables.html

    ad4. z tego co wiem to Ophcrack działa też pod *NIXami i MacOSem :), a wybrałem go dlatego, że o ile się nie mylę to jego autorem jest twórca tęczowych

  6. Winhelp napisał(a):

    Hm, może się ośmieszę, ale:
    Pobieramy hasło od użytkownika. Haszujemy md5, solimy i mamy jakiśtamciągmd5 sól. I teraz się pytam, skoro zapisujemy i hasz i sól to czy trzeba sprawdzić samo md5 i olać sól czy co? Bo chyba nie do końca zrozumiałem ;)

  7. Michał `Bełdzio` Ławicki napisał(a):

    Sprawdzamy oba tzn:

    # pobierasz od użytkownika hasło
    # wyciągasz z bazy sól
    # dodajesz sól do hasła i hashujesz
    # porównujesz otrzymany hash z hashem z bazy

  8. #zainteresowany# napisał(a):

    Czy SHA-512 są, jak na razie, w miarę bezpieczne i co z bezpieczeństwem HMAC?

  9. Michał `Bełdzio` Ławicki napisał(a):

    HMAC dodaje do hasha dodatkow ciąg znaków czyli działa na podobnej zasadzie jak nasze dodawanie soli.

    Jak na razie SHA-2 jest odporny na kolizję oraz nie są znane inne metody przełamania go, tak więc zdecydowanie lepiej korzystać z niego niż z SHA-1

  10. dr_bonzo napisał(a):

    seed'em sie inicjuje generator zmiennych pseudo losowych

    a salt dokleja sie do hasla przed jego hashowaniem

  11. Abel napisał(a):

    Chcę tylko powiadomic ludzi korzystających z tego artykulu. Funkcja md5(), została złamana i hasło zakodowane za pomocą jej można łatwo odczytac. (Patrz wikipedia – z tego co pamietam jest tam link do strony gdzie mozna zlamac haslo zakodowane md5()) Obecnie powinno stosowac sie funkcje sha1(). Ona także koduje ciąg znaków, tyle ze zamiast kodowac na 32 znaki koduje na 40 znaków. ;)

  12. Michał `Bełdzio` Ławicki napisał(a):

    1. md5 nie koduje tylko hashuje
    2. łamanie md5 opiera się na tęczowych tablicach, o których jest między innymi ten art

  13. Winhelp napisał(a):

    A wpadło mi jakoś tak do głowy – może po prostu:

    md5(md5($haslo)));

    ???

  14. Michał `Bełdzio` Ławicki napisał(a):

    Nie ma problemu :) wszystko co doprowadzi do "bezpiecznej" ilości znaków zwiększy nasze bezpieczeństwo

  15. Morkai napisał(a):

    Ciekawy artykuł nawiązujący do tematu: Password hashing howto and hownotto.

    Jest tam m.in. o md5(md5($haslo)) ;)

  16. Morkai napisał(a):

    btw. przydałoby się wracanie do notki po dodaniu komentarza :P

  17. zawsze można podwójnie hasło zakodować jak w enigmie i po sprawie. rainbow tables będą miały trudniej

  18. co do sensu podwójnego hashowania hasła można poczytać tu -> http://forum.php.pl/index.php?showtopic=44156

    tak jak napisałeś będą miały trudniej, a jeśli zamiast robić wielokrotnych hash posolisz hasło, po „złamaniu” hasła nie otrzymasz go w jawnej postaci tak więc będzie trudniej :)

  19. chciałbym zauważyć, że w kodzie :
    $passwd = $_GET[‚passwd’];
    $length = 9 – strlen( $passwd );
    $dots = str_repeat( ‚.’, $length );
    echo md5( $passwd . $spaces ); <- dokładnie ta linijka zawarłeś zmienna $spaces która nie jest zdefiniowana więc prawdopodobnie chodzi tam o $dots … to takie w sumie info dla osób kopiujących żywcem :D

    i jeszcze jedno odnośnie echo md5( $passwd . $salt ); ponieważ już była jedno pytanie na ten temat to trzeba by tu napisać sprostowanie bo echo nie zapisuje tylko to jest polecenie wyjścia (na chłopski rozum wyświetlenie na ekranie) ale w tym przypadku zakładam że autorowi chodziło o prezentacje wyniku, bo jeśli miał to być zapis to trzeba by tam zdefiniować zmienna lub cokolwiek gdzie miało by to być zapisane ;)

  20. @Com dzięki za komentarz. Kod poprawiony. Jeśli chodzi o „echo” i komentarza zapisu, to komentarz miał wskazać nie tyle opis poprzedniego wiersza, co zakomunikować, że w jego miejscu powinien znaleźć się kod odpowiedzialny za zapis danych.

  21. Faktycznie jak na to teraz patrze to masz racje.. Chyba będę musiał tu częściej wpadać bo widzę że moja wiedza jak na razie jest niewielka, a dzięki Twoim wpisom dosyć dobrze udało mi się zabezpieczyć swojego cms-a. Z braku szyfrowania ssl wykorzystałem hashowanie md5 i szyfrowanie base64 ( skrypty w js ) przed wysłaniem $_POST , tylko mam takie pytanie czy te rozwiązanie nie jest trochę ryzykowne? Bo właśnie zacząłem się zastanawiać czy ten sposób jest dobry…

  22. Czy solenie nie jest ryzykowne? Raczej nie, napisz co masz na myśli.

    btw base64 nie jest zbyt „rozbudowanym” sposobem zabezpieczania – dość łatwo można sobie z nim poradzić

  23. Chodzi mi o to że mam formularz np logowania i dałem tam do input haslo onkeyup=”this.form.haslo.value = Base64.encode(this.value)” i do input submit onclick=”document.getElementById(‚haslo1’).value = hex_md5(document.getElementById(‚haslo’).value);” no i teraz mam pytanie czy jak to potem prześle w $_POST[‚haslo1’] do pliku porównującego z plikiem z bazy to czy to będzie bezpieczne.. tak wiem że base64 nie jest dobrym sposobem szyfrowania dlatego umieściłem go w sumie md5

  24. Dwie rzeczy tu wiedzę. Po pierwsze jak będziesz hashował po stronie klienta, to po stronie serwera nie dodasz już soli – chyba, że będziesz solił hash i ponownie hashował, ale nie jest to dobra metoda. Samo base64 za wiele Ci tu nie da. Jeśli miałoby być to dodatkowe „wzmocnienie” hasha, to raczej nie zadziała, bo atakujący patrząc w kod od razu wie co się dzieje z hasłem.

  25. Masz rację, dzięki za odpowiedź… no to wygl na to, że tradycyjny sposób dalej wygrywa :D no chyba że dało by się value zaszyfrować przed wysłaniem w php, ale jakimś własnym skryptem tylko jeszcze nie bardzo wiem jak :D bo solenie hasha to się mija z celem tak jak mówisz a sam base64 to tak jakby nic nie było, a tylko nie potrzeba większa ilość zapytań do serwera… no nic będę eksperymentował ^^

Trackbacks & Pingbacks

  1. Mit md5 upada - BarsWF i nieskuteczne szyfrowanie md5 | IT Tech Blog

    […] samym md5 i bezpieczeństwie poczytajcie beldzio.com i […]

  2. Między neuronami a bitami » Blog Archive » Parę słów o szyfrowaniu i bezpieczeństwie

    […] Aby zabezpieczyć się przed tym należy “posolić”  hasło przed haszowaniem, czyli dodać pewien ciąg znaków np: md5( $passwd . $salt ); (więcej: tutaj) […]

  3. Omijanie haseł w plikach /etc/passwd i /etc/shadow/ – cz. 2 — wz kOsMoS

    […] systemu oraz uniemożliwić jego złamanie (na ten temat można przeczytać np. na tej stronie http://www.beldzio.com/bezpieczenstwo-funkcji-hashujacych). Powszechnie solone hasła są w pliku /etc/shadow. (np. “pass” = 1$ozdpg0V0 $ […]

Dodaj komentarz