21232f297a57a5a743894a0e4a801fc3
Koniec świata nie nadszedł 21 grudnia 2012 jak przewidywali niektórzy. Teraz, prawie tydzień później można to powiedzieć z nieomal stuprocentową pewnością. I skoro gorące ramiona apokalipsy nie otuliły naszej planety, by w oczyszczających płomieniach przynieść nową jakość, trzeba radzić sobie z codziennością. Dorzucę swoje trzy grosze w kwestii bezpieczeństwa, a dokładniej - szyfrowaniu haseł w aplikacjach www.
Ponad dwa tygodnie temu ukazała się informacja na łamach dobrychprogramów o clastrze zbudowanym w celu łamania haseł. Od razu pojawiły się komentarze o tym, że koniec świata nadchodzi wcale nie w związku z przepowiednią Majów, a ze strony fatalnie zabezpieczonych haseł i łatwości ich uzyskania. Powalczymy więc z tymi demonami.
Teoria
Zacznijmy od procesu logowania do aplikacji www, powiedzmy klasycznego procesu. Polega on na uzupełnieniu formularza, w którym podajemy login i hasło. Nie ma znaczenia czy, dane te przesyłane są https, czy http. Chodzi o sam proces autoryzacji. Serwer przyjmuje te dane i odpytuje bazę danych. Przykładowe zapytanie:
select * from `users` where `login` = 'login' and `haslo` = 'haslo';
W takim przypadku oczywiście w bazie zapisane jest jawnym tekstem nasze hasło. Sytuacja archaiczna i nie chce mi się wierzyć, że jakikolwiek system posiada jeszcze tego typu cukierki (z drugiej strony phpbb jeszcze niedawno [a być może w dalszym ciągu!] zapisuje właśnie w ten sposób hasło i login do serwera SMTP). Jeśli baza zwróci rekord - logowanie najczęściej jest udane i następuje proces zakładania sesji (lub inna, zaplanowana akcja).
OK, a co więc może być zagrożeniem? Wyróżnijmy trzy:
- Atak słownikowy/bruteforce na aplikację www
- Wyciek bazy danych (przez SQLi, albo inny, może coś o tym napiszę...)
- Pełna kompromitacja serwera, dostęp do kodu i bazy
Atak słownikowy/bruteforce na aplikację www
Atak ten polega na automatycznej próbie zalogowania się do aplikacji www (przy założeniu, że znamy login lub jest on łatwy do odgadnięcia) przy pomocy wygenerowanych słowników (czyli zestawieniu na przykład najczęściej pojawiających się haseł, poszerzonym o wszelkie wariacje okołologinowe. Często słowniki są specjalizowane pod względem języka, którym posługuje się właściciel konta) lub przy pomocy generatora haseł (który, w najprostszym układzie, tworzy kolejne stringi korzystając z kolejnych liter alfabetu i cyfr). Ataki te są często bardzo skuteczne, a dobre słowniki mają wysoką skuteczność (dochodzącą do kilkudziesięciu procent) i wysoką cenę.
Twórcy aplikacji www mają bardzo prosty i w zasadzie skuteczny sposób przeciw tego typu atakom - wystarczy inkrementować ilość niepoprawnych logowań i po x próbach blokować konto. Jednak jak każdy kij - ma to dwa końce. Daje to bardzo proste narzędzie do zaplanowanego blokowania kont ofiar. Jest to być może powód, dla którego pozostawia się otwartą drogę do tej metody (tzw. ryzyko resztkowe, albo ryzyko szczątkowe).
Wyciek bazy danych
Wbrew pozorom pozyskanie w miarę aktualnej bazy danych przeróżnych serwisów nie jest takie trudne, jakby się mogło wydawać. Wystarczy tylko trochę pogooglać. Wyobraźmy sobie sytuację, że mamy dostęp do bazy danych i nic poza tym. Co z tym zrobić? O ile hasła są zapisane tekstem jawnym - możemy wszystko. Jeśli nie... A co to znaczy, że nie są w tekście jawnym? To znaczy, że na stringu 'haslo' została wykonana jakaś operacja skrótu, która daje w outpucie zawsze tę samą wartość, na dodatek unikatową. Taką (popularną) funkcją jest na przykład md5. Nawiasem mówiąc - tytuł tego wpisu to właśnie wynik takiej funkcji zastosowanej na stringu 'admin'.
Teoretycznie - nie istnieje taka funkcja f(x) = y, że md5(y) = x. W praktyce - nie musi istnieć. Wróćmy na chwilę do tytułu wpisu. Co się stanie, gdy wrzucę do googla taki zlepek literek i cyferek? W pierwszym wyniku uzyskam string, którego użyłem. Jak to działa? Dość prosto - tworzone są bazy danych (rainbow tables), które przechowują dane. To w nich wyszukiwane są odpowiednie wartości. Takich generatorów po necie wala się mnóstwo, choć nie każde z nich to tablice tęczowe.
Jak się więc bronić? Jest kilka sposobów.
Zacznijmy od popularnego słowa-klucza - sól. Hasło przed poddaniem funkcji skrótowej solone jest (urozmaicane) przez inny string. Idealnie jest, gdy i on jest losowy (choć wtedy musi być gdzieś przechowywany, więc pewnie w tej samej bazie, do której mamy dostęp). I tak md5('admin_sol') to nie to samo co md5('admin_Sol'). Sprawa już na etapie wielkości liter ma znaczenie (choć należy pamiętać, żeby nigdy nie zmieniać wielkości liter w samym haśle). Oczywiście algorytm może być bardziej skomplikowany (md5('admin'.md5('sol'))). Co więcej - jeśli atakujący nie ma dostępu o kodu aplikacji, a logika logowania nie została przeniesiona do bazy - jest wysoce nieprawdopodobne złamanie takiego (dobrze) osolonego hasła w sensownym czasie.
Poza soleniem hasła można stosować inne metody uwierzytelniania. Na przykład podwójne uwierzytelnianie, jak proponuje obecnie google, albo podawanie w procesie logowania nie wszystkich znaków hasła (jak w przypadku banku BPH. Swoją drogą - czy to nie oznacza, że posiadają w bazach zapisane hasło jawnym tekstem?)
Pełna kompromitacja serwera
W takiej sytuacji... no generalnie jest przechlapane. Ale hasła w dalszym ciągu mogą pozostać bezpieczne. Przy odpowiednim zagnieżdżeniu funkcji skrótów czas potrzebny na przełamanie każdej z nich sumuje się na czas potrzebny do złamania całego hasła. Często czas ten jest tak duży, że nie opłaca się podejmować wyzwania. Z drugiej jednak strony - zwiększa to także load serwera w przypadku tak prostego procesu jak zalogowanie.
Inne sposoby łamania skrótów
Tak to jest z funkcjami skrótowymi, że poza słownikową metodą łamania wymyślane są inne. Jedną z nich jest teoria kolizji skrótów. Teoria ta mówi, że jest możliwe wyznaczenie takiego stringu z, że md5(x) = md5(z) = y. To znaczy stworzenia innego stringa, dla którego wynik funkcji będzie taki sam, jak przy poszukiwanym haśle. Podanie więc takiego stringu w procesie logowania powinno pozwolić na autoryzacje. Jednak osolenie hasła praktycznie uniemożliwia wykonanie tego ataku na aplikację www (abstrahując już od faktu, że wyznaczenie takiej kolizji jest bardzo trudne).
Praktyczne podsumowanie
Co z tego wszystkiego wynika? Zacznijmy od początku...
- Atak słownikowy/bruteforce na aplikację www -Tutaj jakość naszego hasła wyznacza stopień trudności złamania. Im bardziej skomplikowane i niesłownikowe hasło, tym mniejsza szansa na jego złamanie
- Wyciek bazy danych - Tym razem już nie tylko jakość naszego hasła ma znaczenie. Jeśli developer aplikacji zastosował solenie, albo inne metody - jakość naszego hasła jest dopiero wtórnym wyznacznikiem bezpieczeństwa. Jednak warto pamiętać, że łatwe hasło pozwala opracować odwrotny algorytm do stosowanego w aplikacji
- Pełna kompromitacja serwera - Jeśli uda się obedrzeć z tajemnicy algorytm stosowany w aplikacji - kolejny raz wyznacznikiem bezpieczeństwa jest jakość hasła.
Nie warto więc zaprzątać sobie głowy sposobami, w jakie możemy utracić nasze hasło (chyba, że jesteśmy developerami aplikacji). Najlepiej stosować skomplikowane hasła zawsze. Nie ma też sensu popadać w skrajną paranoję. I tak nie mamy pewności, jak działa aplikacja. Podobnie jak w przypadku prowadzenia samochodu. Możemy być najlepszymi kierowcami z zapiętymi pasami, a na parkingu zarysuje nas ktoś otwierając drzwi.
PS. wiem, że md5 jest już od dawna odradzanie, ze sha1, albo nawet sha2. Ta funkcja była tylko przykładem.