Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

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. 

internet bezpieczeństwo programowanie

Komentarze

0 nowych
  #1 27.12.2012 13:44

Podziwiam, że potrafisz pisać w sposób, że nawet dla mnie jest to zrozumiałe.

alucosoftware   7 #2 27.12.2012 14:03

Świetny wpis.

ziggurad   11 #3 27.12.2012 14:10

Bardo dobry wpis.

Osobiście dodałbym jeszcze akapit o SQL Injection i jeśli mówimy o PHP np zabezpieczaniu się za pomocą PDO ale powyższy teks można uznać za uniwersalny jeśli mówimy o technologii.

  #4 27.12.2012 14:15

W phpBB nadal wygląda to tak jak opisałeś ale... czy widzisz jakąś sensowną alternatywę?
Hasło do SMTP jest używane przy wysyłaniu emaili, jest więc potrzebne nawet wtedy, gdy nikt nie poda żadnych danych do zamiany na hash - musi być w momencie logowania do serwera poczty w formie plain. Możemy oczywiście w bazie trzymać postać zaszyfrowaną, np. AESem, no ale... co to da? Nic, bo klucze też muszą być albo w bazie, albo w plikach na serwerze, gotowe do rozszyfrowania hasła gdy te będzie potrzebne.

Atak słownikowy/bruteforce na aplikację www - a nie lepiej dać po określonej nieudanej liczbie prób dodatkowy czynnik sprawdzający np. captcha, jakieś dodatkowe pole jak przy antyspamach itd.? To powoduje, że nie musimy faktycznie blokować konta i wymagać od prawdziwego użytkownika jakichś większych rzeczy do zrobienia (wystarczy, że sam przejdzie ten dodatkowy mechanizm). Oczywiście to powinno być zrealizowane w taki sposób, aby automat miał maksymalnie utrudnioną robotę, bo w przeciwnym wypadku będzie w ramach ataku bruteforce również rozwiązywał czynnik.
Poza tym niekoniecznie zgodę się że skomplikowanie hasła zwiększy jego jakość. Teraz bruteforce leci naprawdę szybko dzięki kartom graficznym... Co lepiej robić? Zwiększać długość hasła, mała anegdota:
http://xkcd.com/936/

Co do hashowania haseł - przede wszystkim, nie wymyślajmy koła na nowo, bo najczęściej i tak nic to nie da. Tutaj dosyć ciekawy artykuł na ten temat:
http://crackstation.net/hashing-security.htm
Tak nawiasem - do haseł wspomniane wcześniej phpBB używa phpass.

Autor edytował komentarz.
Axles   16 #5 27.12.2012 15:02

Fajny wpis na prawdę. Coś tam teorii znałem, ale ty mi zdecydowanie to przybliżyłeś.

tfl   8 #6 27.12.2012 15:28

dziekuje za komentarze

@lukasamd

PHPBB - ja bym mimo wszystko trzymalbym w php. z mojego skromnego doswiadczenia wynika, ze majac konto mailowe przeznaczone dla forum ma sie konto mailowe administratora, a w konsekwencji jego konto na forum, a wiec takze wszystkie inne.

Captcha to doskonaly patent! Oboma rekami sie podpisuje pod tym.

Co do skomplikowania i jakosci hasla. Masz racje, naduzylem tego slowa, choc staralem sie pilnowac i pisac o jakosci.

Autor edytował komentarz.
  #7 27.12.2012 15:36

Ja tam jeżeli mam używać SMTP to robię od wysyłki jakieś osobne konto. Nawet w zabezpieczonej formie wolałbym tego nie trzymać na serwerze z samym serwisem (jakikolwiek, czy to phpbb, czy wordpress czy jeszcze co innego), bo to zbyt ważna rzecz.
No ale to i tak tylko w wyjątkowych sytuacjach, bo preferuję w ogóle nie używanie SMTP - jest wolniejsze niż zwykły mail.

meron11   3 #8 27.12.2012 18:52

Dodam od siebie jakze banalne stwierdzenie że sól nie utrudnia łamania hasła, tylko opóźnia, kwestia generowania tablic w przypadku md5.Spotkałem się z szyfrowaniem danych w bazie algorytmem który uzywał klucza zapisanego w pliku php, bardzo dobre posunięcie w przypadku sql injection kiedy nie mamy dostępu do pliku z kluczem.

budda86   9 #9 27.12.2012 19:13

Ja wiem, że Autor wie, ale z tekstu nie wynika to wprost - w przypadku ataku słownikowego/bruteforce na aplikację nie ma znaczenia, czy hasła są trzymane jako plain text, czy też haszowane.

Ponadto, nawet najlepsze i najbardziej skomplikowane hasło nie jest wiele warte, jeśli stosujemy je wszędzie - zwłaszcza w parze z tym samym adresem e-mail :)

@lukasamd
Captcha to zależy jaka, bo niektóre są łamane tak szybko, że właściwie niezauważalne :)

Co do tego odcinka xkcd - jest on trochę naciągany. Fakt, że w 'prostym-do-zapamiętania-i-trudnym-do-złamania' haśle jest wiele znaków, co czyni bruteforce kłopotliwym. Ale atak słownikowy? Mamy tu kombinację tylko 4 niewyszukanych słów. Jak myślicie, jak wiele może być kombinacji? :)

  #10 27.12.2012 21:01

@budda86:
No tak, ale widziałeś słowniki trzymające np. całe zdania? Słowniki mają zapisane słowa, ale już takie gdzie są sprawdzane przy ataku słownikowym 2 słowa obok siebie (separator to też wielka niewiadoma) to już rzadkość.

Pigmej   5 #11 27.12.2012 22:47

Mała uwaga:
md5('admin'.md5('sol'))) nie poprawia w żaden sposób jakości solenia. A nawet ją zmniejsza (kłania się entropia tutaj).

wojmal   6 #12 28.12.2012 01:05

Dzięki za wpis. Jasno i klarownie wyłuszczone najważniejsze rzeczy. Prośba do Pigmeja: dałoby radę rozwinąć tę myśl o entropii i md5('admin'.md5('sol')), entropię kojarzę i świta mi pewna teoria, ale chciałbym się upewnić, czy nie jest ona błędna (skrót ze skrótu jest słabym skrótem).

tfl   8 #13 28.12.2012 08:41

Co do tej entropii... to sam nie bardzo rozumiem komentarze pod tekstem na jej temat... zgodnie z moja wiedza z entropia jest mniej wiecej tak...


entropie (informacyjna, czyli taka, ktora da sie mierzyc "jakosc" hasla, czyli ile musimy razy probowac, zeby odgadnac nasze haslo) liczymy ze wzoru:

2^ilosc_bitow_entropii

Natomiast ilosc bitow entropii ze wzoru:

IBE = log2(N)

gdzie N jest iloscia znakow zbiorow, z ktorych haslo moze sie skladac. Jesli wiec haslo sklada sie z malych liter a-z, ktorych jest 26, to IBE = 4,7, dla jednego znaku w hasle. Entropia wynosi 25,9.

W przypadku hasel skladajacych sie z innych znakow entropia rosnie, gdyz sumowane jest N. W przypadku wzrostu ilosci znakow zwielokrotnianie jest IBE. W przypadku hasla posiadajacego wielkie i male litery, cyfry i znak specjalny i bedecego czteroznakowcem bitow entropi per znak jest okolo 6,5, a cale haslo ma tych bitow ponad 26 (nieco). Tymczasem haslo czteroznakowe ale posiadajace tylko male litery ma tych bitow prawie 19.

Samo hashowanie hasha jest o tyle niebezpieczne, ze zaweza ilosc zbiorow znakow. W md5 sa tylko cyfry i litery od a do f. Mamy wiec N rowne 16. Bitow entropi per litera jest wiec 4. Razy ilosc znakow (32) daje nam ilosc bitow entropii rowna 128. W dzisiejszych czasach 128 bitow to po prostu malo, ale poza md5 sa inne funkcje skrotu :)


PS. metoda obliczania entropii, ktora przedstawilem jest uproszczona.

bachus   19 #14 28.12.2012 10:58

Fajnie piszesz - nawet ja zrozumiałem ;-)

  #15 31.12.2012 00:13

how about h(x) = sha2(sha1(sól(x)) + md5(sól(x)) ^ md5(sól(MAX-x)) + sól(x)) ?
tego typu zabawa powinna chyba załatwić sprawę, choć technologie internetowe to nie moja działka ;)

W_tym_temaciE   5 #16 05.01.2013 23:21

@tfl
"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)."
Możliwe że nie wszędzie jest taka możliwość... ale można by przecież zaimplementować w mechaniźmie logowania skrypt, który wraz ze zwiększeniem się liczby prób logowania z konkretnego komputera zwiększa szansę na rzucenie "kontrolowanym błędem"?
Tzn. że jeśli ktoś loguje się po raz pierwszy, szansa wynosi 0%. Jak po raz drugi, to 1%.
I tak dalej, tylko że np. przy 20 próbach szansa wynosiłaby już 40%.

tfl   8 #17 06.01.2013 11:51

@W_tym_temaciE

Co to znaczy "kontrolowany błąd"? I czym sie rozni Twoj sposob od opisanego przeze mnie, poza tym, ze jest bardziej skomplikowany, a efekt daje ten sam ?

  #18 25.09.2013 02:26

@tfl Co sądzisz o soleniu hasła w każdej warstwie, przez którą przechodzi owe hasło w trakcie autoryzacji? Zależnie od tego, do której warstwy uzyska dostęp włamywacz, hasła pozostaną w dalszym ciągu zabezpieczone.

Osobiście korzystam z takiego podejścia:
- jedna sól w pliku .htxxx.php (plik ładowany poprzez pare_ini_file())
- kolejna sól w zaciemnionym pliku php, konfiguracyjnym, modułu autoryzacji (zaciemnianie ma cholernie mocno utrudnić, nie uniemożliwić odczytanie)
- kolejna sól, wygenerowana losowo dla każdego użytkownika, jako dodatkowa kolumna w bazie
- całość w kolejności np. sól2.sól1.hasło.sól3, trzymane w bazie po shaxxx'iksowaniu

--

Co do metod zabezpieczania formularza logowania.

Przede wszystkim system musi spełniać kryteria:
- email użyty do rejestracji nie jest w domenie typu 10 Minute Mail,
- hasło do danego konta nie widnieje na żadnej z krajowych list najpopularniejszych haseł,
- przechowywane są lokalnie hashowane (mogą być posolone trzema solami) adresy IP, z których logowano się poprawnie na dane konto,
- przechowywane są globalnie niehashowane adresy IP, z których dokonywano nieudanych prób logowania wraz z licznikiem tych prób,
- istnieje globalny średni współczynnik nieudanych logowań względem udanych w ciągu dnia,
- istnieją lokalne liczniki nieudanych logowań z jednego adresu IP oraz z jednej sesji,
- CSRF,
- HTTPS,
- możliwość wysłania, na żądane użytkownika, kodu PIN do formularza logowania.

Możliwe przypadki ataku to permutacje bez powtórzeń zbioru:
- źródło: jedno IP, kilka IP, wiele IP,
- cel: jedno konto, kilka kont, wiele kont,
- dodatkowo: IP jest na liście zaufanych adresów przypisanych do atakowanego konta, IP jest na którejś z list zaufanych adresów, IP nie ma na żadnej liście.

Interesuje Cię zabezpieczenie na którąś z kombinacji przy spełnionych kryteriach?