Sprawdzone metody: solenie i pieprzanie haseł?

145

Natknąłem się na dyskusję, w której dowiedziałem się, że to, co robię, nie jest w rzeczywistości soleniem haseł, ale ich pieprzeniem, i od tego czasu zacząłem robić obie funkcje takie jak:

hash_function($salt.hash_function($pepper.$password)) [multiple iterations]

Ignorując wybrany algorytm skrótu (chcę, aby było to omówienie soli i papryki, a nie konkretnych algorytmów, ale używam bezpiecznego), czy jest to bezpieczna opcja, czy powinienem robić coś innego? Dla osób niezaznajomionych z terminami:

  • Sól jest losowo wygenerowaną wartość zwykle przechowywane z napisu w bazie zaprojektowany tak, by nie dało się korzystać tabele mieszania do łamania haseł. Ponieważ każde hasło ma swoją własną sól, wszystkie muszą być brutalnie wymuszone indywidualnie, aby je złamać; Jednak ponieważ sól jest przechowywana w bazie danych wraz ze skrótem hasła, naruszenie bezpieczeństwa bazy danych oznacza utratę obu.

  • Pieprz jest wartością statyczną całej witrynie przechowywane oddzielnie od bazy (zwykle zakodowane w kodzie źródłowym aplikacji), które ma być tajne. Jest używany po to, aby włamanie do bazy danych nie spowodowało, że cała tabela haseł aplikacji była brutalnie wymuszona.

Czy jest coś, czego mi brakuje i czy podlewanie i pieprzanie moich haseł jest najlepszą opcją ochrony bezpieczeństwa mojego użytkownika? Czy istnieje potencjalna luka w zabezpieczeniach, aby zrobić to w ten sposób?

Uwaga: Załóżmy na potrzeby dyskusji, że aplikacja i baza danych są przechowywane na oddzielnych komputerach, nie udostępniaj haseł itp., Więc naruszenie serwera bazy danych nie oznacza automatycznie naruszenia serwera aplikacji.

Glitch Desire
źródło
3
Nie dość duplikat, ale bardzo podobne: stackoverflow.com/questions/16594613/...
ircmaxell
2
Duplikat między witrynami: security.stackexchange.com/q/3272/2113
Jacco,

Odpowiedzi:

307

Dobrze. Skoro muszę napisać o tym przejęcia i nad , zrobię jeszcze jedną odpowiedź na kanoniczny pieprzu sam.

Pozorna zaleta papryki

Wydaje się dość oczywiste, że papryka powinna sprawić, że funkcje skrótu będą bezpieczniejsze. Chodzi mi o to, że jeśli atakujący dostanie tylko twoją bazę danych, hasła twoich użytkowników powinny być bezpieczne, prawda? Wydaje się logiczne, prawda?

Dlatego tak wielu ludzi uważa, że ​​papryka to dobry pomysł. To ma sens".

Rzeczywistość papryki

W dziedzinie bezpieczeństwa i kryptografii „sens” nie wystarczy. Coś musi być możliwe do udowodnienia i mieć sens, aby można było to uznać za bezpieczne. Dodatkowo musi być możliwe do zaimplementowania w sposób możliwy do utrzymania. Najbezpieczniejszy system, którego nie można utrzymać, jest uważany za niezabezpieczony (ponieważ jeśli jakakolwiek jego część ulegnie awarii, cały system się rozpadnie).

A papryka nie pasuje ani do modeli możliwych do udowodnienia, ani do konserwacji ...

Teoretyczne problemy z papryką

Teraz, gdy przygotowaliśmy scenę, przyjrzyjmy się, co jest nie tak z papryką.

  • Podawanie jednego haszyszu do drugiego może być niebezpieczne.

    W twoim przykładzie tak hash_function($salt . hash_function($pepper . $password)).

    Z doświadczenia wiemy, że „zwykłe wprowadzenie” jednego wyniku skrótu do innej funkcji skrótu może zmniejszyć ogólne bezpieczeństwo. Powodem jest to, że obie funkcje skrótu mogą stać się celem ataku.

    Dlatego algorytmy takie jak PBKDF2 używają specjalnych operacji do ich łączenia (w tym przypadku hmac).

    Chodzi o to, że chociaż nie jest to wielka sprawa, to również nie jest rzeczą trywialną po prostu rzucić. Systemy kryptograficzne są zaprojektowane tak, aby unikać przypadków „powinny działać”, a zamiast tego skupiać się na przypadkach „przeznaczonych do pracy”.

    Chociaż może się to wydawać czysto teoretyczne, w rzeczywistości tak nie jest. Na przykład Bcrypt nie może akceptować dowolnych haseł . Zatem przekazywanie bcrypt(hash(pw), salt)może rzeczywiście skutkować znacznie słabszym hashem niż w bcrypt(pw, salt)przypadku hash()zwrócenia ciągu binarnego.

  • Praca przeciw projektowi

    Sposób, w jaki bcrypt (i inne algorytmy haszowania haseł) został zaprojektowany, jest taki, aby działał z solą. Pojęcie pieprzu nigdy nie zostało wprowadzone. Może się to wydawać błahe, ale tak nie jest. Powodem jest to, że sól nie jest tajemnicą. Jest to po prostu wartość, która może być znana atakującemu. Z drugiej strony pieprz jest z definicji tajemnicą kryptograficzną.

    Wszystkie obecne algorytmy haszowania haseł (bcrypt, pbkdf2 itd.) Są zaprojektowane tak, aby przyjmować tylko jedną tajną wartość (hasło). Dodawanie kolejnego sekretu do algorytmu nie było w ogóle badane.

    To nie znaczy, że nie jest to bezpieczne. Oznacza to, że nie wiemy, czy jest to bezpieczne. Ogólne zalecenie dotyczące bezpieczeństwa i kryptografii jest takie, że jeśli nie wiemy, tak nie jest.

    Tak więc dopóki algorytmy nie zostaną zaprojektowane i sprawdzone przez kryptografów pod kątem użycia z tajnymi wartościami (paprykami), nie należy ich używać z aktualnymi algorytmami.

  • Złożoność jest wrogiem bezpieczeństwa

    Wierz lub nie, ale złożoność jest wrogiem bezpieczeństwa . Tworzenie algorytmu, który wygląda na skomplikowany, może być bezpieczne lub nie. Ale szanse są dość duże, że nie jest to bezpieczne.

Znaczące problemy z papryką

  • To nie do utrzymania

    Twoja implementacja papryki wyklucza możliwość obracania klucza pieprzowego. Ponieważ pieprz jest używany na wejściu do funkcji jednokierunkowej, nigdy nie można zmienić pieprzu przez cały okres istnienia wartości. Oznacza to, że musiałbyś wymyślić kilka niefortunnych hacków, aby obsługiwał rotację kluczy.

    Jest to niezwykle ważne, ponieważ jest wymagane za każdym razem, gdy przechowujesz tajemnice kryptograficzne. Brak mechanizmu rotacji kluczy (okresowo i po naruszeniu) to ogromna luka w zabezpieczeniach.

    A Twoje obecne podejście wymagałoby od każdego użytkownika całkowitego unieważnienia hasła przez rotację lub czekania do następnego logowania do rotacji (co może nigdy nie nastąpić) ...

    Co w zasadzie sprawia, że ​​twoje podejście jest natychmiastowe.

  • Wymaga zrobienia własnego Crypto

    Ponieważ żaden obecny algorytm nie obsługuje koncepcji pieprzu, wymaga on albo skomponowania algorytmów, albo wynalezienia nowych do obsługi pieprzu. A jeśli nie możesz od razu zobaczyć, dlaczego to naprawdę zła rzecz:

    Każdy, od najbardziej bezmyślnego amatora po najlepszego kryptografa, może stworzyć algorytm, którego sam nie może złamać.

    NIGDY nie rzucaj własnej krypto ...

Lepszy sposób

Zatem spośród wszystkich opisanych powyżej problemów istnieją dwa sposoby rozwiązania tej sytuacji.

  • Po prostu użyj algorytmów, jakie istnieją

    Jeśli używasz bcrypt lub scrypt poprawnie (przy wysokich kosztach), wszystkie hasła słownikowe oprócz najsłabszych powinny być statystycznie bezpieczne. Aktualny rekord haszowania bcrypt po koszcie 5 to 71k hashów na sekundę. W takim przypadku złamanie nawet 6-znakowego losowego hasła zajęłoby lata. Biorąc pod uwagę, że mój minimalny zalecany koszt to 10, zmniejsza to liczbę haszów na sekundę o współczynnik 32. Więc mówilibyśmy tylko o 2200 hashach na sekundę. W takim przypadku nawet niektóre zwroty słownikowe lub modyfikacje mogą być bezpieczne.

    Ponadto powinniśmy sprawdzać te słabe klasy haseł przy drzwiach i nie zezwalać im na dostęp. Ponieważ łamanie haseł staje się bardziej zaawansowane, powinny też spełniać wymagania jakościowe. To wciąż gra statystyczna, ale przy odpowiedniej technice przechowywania i silnych hasłach każdy powinien być praktycznie bardzo bezpieczny ...

  • Zaszyfruj skrót wyjściowy przed zapisaniem

    W dziedzinie bezpieczeństwa istnieje algorytm zaprojektowany do obsługi wszystkiego, co powiedzieliśmy powyżej. To szyfr blokowy. To dobrze, bo jest odwracalne, więc możemy obracać klucze (yay! Konserwacja!). To jest dobre, ponieważ jest używane zgodnie z projektem. Jest to dobre, ponieważ nie daje użytkownikowi żadnych informacji.

    Spójrzmy ponownie na tę linię. Załóżmy, że atakujący zna Twój algorytm (który jest wymagany ze względów bezpieczeństwa, w przeciwnym razie jest to zabezpieczenie przez ukrywanie). Korzystając z tradycyjnego podejścia pieprzowego, napastnik może stworzyć hasło wartownika, a ponieważ zna sól i wydajność, może brutalnie zmusić pieprz. Ok, to długa szansa, ale jest to możliwe. Za pomocą szyfru napastnik nic nie dostaje. A ponieważ sól jest losowa, hasło strażnika nawet mu nie pomoże. Więc najlepiej im pozostaje, aby zaatakować zaszyfrowaną formę. Oznacza to, że najpierw muszą zaatakować zaszyfrowany skrót, aby odzyskać klucz szyfrowania, a następnie zaatakować skróty. Ale jest wiele badań dotyczących atakowania szyfrów, więc chcemy na tym polegać.

TL / DR

Nie używaj papryki. Jest z nimi wiele problemów i są dwa lepsze sposoby: nieużywanie żadnego klucza tajnego po stronie serwera (tak, jest w porządku) i szyfrowanie wyjściowego skrótu za pomocą szyfru blokowego przed przechowywaniem.

ircmaxell
źródło
6
Dzięki za uwzględnienie ostatniej części szyfrowania wartości skrótu, to jest odpowiedź, z którą w pełni się zgadzam. Gdyby szyfrowanie stało się częścią twojego interfejsu API hasła , nie byłoby powodu, aby go nie używać, więc może ... (chciałbym napisać do niego dokumentację)
martinstoeckli
2
@martinstoeckli: Nie zgadzam się na dodanie etapu szyfrowania do uproszczonego interfejsu API haszowania. Powodem jest to, że przechowywanie sekretów (kluczy) jest o wiele trudniejsze, niż ludzie zdają sobie sprawę, i dość łatwo jest strzelić sobie w stopę. Dla 99,9% użytkowników surowy
plik bcrypt
7
@ircmaxell - po drugiej stronie nic byś nie stracił. W najgorszym przypadku, gdy klucz staje się znany, osoba atakująca musi nadal złamać hash BCrypt (taka sama sytuacja jak bez szyfrowania). To nie to samo, co przechowywanie klucza do szyfrowania danych, chodzi o dodanie klucza tajnego po stronie serwera. Nawet zakodowany klucz chroniłby te słabe hasła, o ile atakujący nie ma kontroli nad serwerem / kodem. Taka sytuacja nie jest rzadkością: poza wstrzyknięciem SQL również wyrzucone kopie zapasowe, wyrzucone serwery… mogą doprowadzić do takiej sytuacji. Wielu użytkowników PHP pracuje na serwerach hostowanych.
martinstoeckli
2
@martinstoeckli Musiałbym zgodzić się tutaj z ircmaxwellem, nie sądzę, że szyfrowanie należy do interfejsu API hasła. Chociaż można zauważyć, że dla maksymalnego bezpieczeństwa szyfrowanie skrótów jest dodatkowym zabezpieczeniem, którego można użyć.
foochow
Mam pytanie dotyczące szyfrowania danych wyjściowych przed przechowywaniem. Jeśli się nie mylę, klucze szyfrowania są zwykle używane do szyfrowania wiadomości w sposób niepowtarzalny lub przejściowy. Jeśli jednak masz 200 000 haseł użytkowników, wszystkie zaszyfrowane tym samym kluczem i przechowywane razem, czy nie ułatwia to ataku na klucz? Masz teraz 200 000 wiadomości, w porównaniu do zaledwie 1 lub 2
AgmLauncher
24

Po pierwsze, powinniśmy porozmawiać o dokładnych zaletach pieprzu :

  • Pepper może chronić słabe hasła przed atakiem słownikowym w szczególnym przypadku, gdy atakujący ma dostęp do bazy danych (zawierającej hashe), ale nie ma dostępu do kodu źródłowego za pomocą pieprzu.

Typowym scenariuszem byłoby wstrzyknięcie SQL, wyrzucenie kopii zapasowych, wyrzucenie serwerów ... Takie sytuacje nie są tak rzadkie, jak się wydaje, i często nie są pod twoją kontrolą (hosting serwera). Jeśli użyjesz...

  • Unikalna sól za hasło
  • Powolny algorytm haszujący, taki jak BCrypt

... silne hasła są dobrze chronione. W takich warunkach brutalne wymuszenie silnego hasła jest prawie niemożliwe, nawet jeśli znana jest sól. Problemem są słabe hasła, które są częścią słownika brutalnej siły lub są ich pochodnymi. Atak słownikowy ujawni je bardzo szybko, ponieważ testujesz tylko najpopularniejsze hasła.

Drugie pytanie brzmi: jak nakładać pieprz ?

Często zalecanym sposobem stosowania pieprzu jest połączenie hasła i pieprzu przed przekazaniem go do funkcji skrótu:

$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);

Jest jednak jeszcze lepszy sposób:

$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);

Pozwala to nie tylko na dodanie sekretu po stronie serwera, ale także na wymianę $ serverSideKey, jeśli jest to konieczne. Ta metoda wymaga nieco więcej pracy, ale jeśli kod już istnieje (biblioteka), nie ma powodu, aby go nie używać.

martinstoeckli
źródło
Więc można powiedzieć, w skrócie, że pieprz zwiększa bezpieczeństwo, a nie tylko sól? Dzięki za pomoc we wdrożeniu.
Glitch Desire
1
@LightningDust - Tak, w przypadku słabych haseł, o ile pieprz pozostaje tajemnicą. Łagodzi niektóre dobrze zdefiniowane typy zagrożeń.
martinstoeckli
@martinstoeckli zdecydowanie dobry sposób na wdrożenie tego. Dobrze widzieć, że ktoś z pewnym doświadczeniem w zakresie bezpieczeństwa obsługuje tę metodę. Czy AES_ENCRYPT($passwordHash, $serverSideKey)wywołanie MySQL byłoby również odpowiednim sposobem realizacji tego?
foochow
1
@Foo_Chow - Nie znam implementacji funkcji MySQL, ale wygląda na to, że używali trybu EBC, aby uniknąć wektora IV. Wraz ze znanym tekstem jawnym (wartości skrótu zawsze zaczynają się tymi samymi znakami), może to stanowić problem. Na mojej stronie domowej opublikowałem przykładową implementację, która obsługuje to szyfrowanie.
martinstoeckli
@martinstoeckli interesujący, niezbyt zaznajomiony z koncepcjami; wydaje się jednak, że IV byłby pożądany dla najbardziej solidnych wyników. Nie wydaje się zwiększać kosztów ogólnych dla dodatkowej korzyści.
foochow
2

Celem solenia i pieprzu jest zwiększenie kosztu wstępnie obliczonego wyszukiwania hasła, zwanego tabelą tęczową.

Ogólnie rzecz biorąc, próba znalezienia kolizji dla pojedynczego skrótu jest trudna (zakładając, że hash jest bezpieczny). Jednak w przypadku krótkich skrótów możliwe jest użycie komputera do wygenerowania wszystkich możliwych skrótów do wyszukiwania na dysku twardym. Nazywa się to Rainbow Table. Jeśli utworzysz tęczową tabelę, możesz wyjść w świat i szybko znaleźć wiarygodne hasła dla dowolnego (niesolonego, nieuporządkowanego) hasha.

Chodzi o to, aby tablica tęczowa potrzebna do zhakowania listy haseł była wyjątkowa. W ten sposób marnujesz więcej czasu na atakującego, aby zbudować tęczowy stół.

Jednak celem soli jest to, aby tablica tęczowa dla każdego użytkownika była unikalna dla użytkownika, co dodatkowo zwiększa złożoność ataku.

Naprawdę celem bezpieczeństwa komputerowego prawie nigdy nie jest uczynienie go (matematycznie) niemożliwym, po prostu matematycznie i fizycznie niepraktycznym (na przykład w bezpiecznych systemach obliczenie hasła pojedynczego użytkownika wymagałoby całej entropii we wszechświecie (i więcej)).

Aron
źródło
Czy więc sól + pieprz zapewnia większe bezpieczeństwo niż sama sól? A może lepiej byłoby zostawić pieprz i uruchomić więcej iteracji skryptu?
Glitch Desire
2
Najważniejsze w przypadku tęczowego stołu jest to, że nie tworzysz go dla konkretnego ataku, pobierasz już istniejący. Dostępne są długie tęczowe tabele dla popularnych algorytmów wyznaczania wartości skrótu, które dzieli Cię od Google!
Richard,
1
@LightningDust Sam nie mogę wymyślić żadnego powodu. Jednak Richard w drugim wątku wymyślił jeden. Możesz ukryć pieprz w swoim kodzie źródłowym, co oznacza inne miejsce, do którego Twój atakujący musi uzyskać dostęp, aby zebrać tęczową tabelę.
Aron,
@Aron - Tak właśnie myślałem, skoro mamy serwery aplikacji oddzielone od serwerów baz danych (to znaczy, jeśli dostaniesz się rootna nasz serwer db, nadal nie masz dostępu do naszego serwera aplikacji), to ukrywający się pieprz w kodzie źródłowym (w nasz plik konfiguracyjny) zapewni dodatkowe bezpieczeństwo.
Glitch Desire
1

Nie widzę zapisywania wartości zakodowanej na stałe w kodzie źródłowym jako mającego jakiekolwiek znaczenie dla bezpieczeństwa. To bezpieczeństwo poprzez mrok.

Jeśli haker zdobędzie Twoją bazę danych, będzie mógł brutalnie wymuszać hasła użytkowników. Hakerowi nie zajmie dużo czasu, jeśli uda mu się złamać kilka haseł, aby zidentyfikować Twój pieprz.

Sven
źródło
1
Spowodowałoby to, że wstępnie obliczona tablica tęczy dla tablicy niesolonych haseł byłaby bezużyteczna. Krótko mówiąc, nawet gdyby napastnik znał twój pieprz, musiałby stworzyć nowy tęczowy stół.
Aron,
3
Wzmacnia hash na podstawie danych niedostępnych w bazie, co jest dobrą rzeczą. Rzeczy w bazie danych mogą potencjalnie zostać ujawnione w lukach - jest mniej prawdopodobne, że wartość w kodzie zostanie uzyskana w ten sam sposób.
Richard
Sole to funkcje jednokierunkowe, nawet skuteczne wymuszenie brutalnego hasła dałoby tylko to hasło i nie pomogłoby w uzyskaniu samej wartości pieprzu.
Glitch Desire
1
@LightningDust Myślę, że masz na myśli „Hashe to funkcje zapadni”. Tak, niemożliwe jest ustalenie ilości soli i / lub pieprzu na podstawie bezpiecznego skrótu (w rzeczywistości jest to definicja bezpiecznego skrótu).
Aron,
6
@Aron Security Through Obscurity może być ważną techniką używaną jako warstwa obrony. Chodzi o to, że nigdy nie należy polegać na nim jako na obronie, ale zamiast tego używać go do „spowolnienia napastnika”. Gdyby tak nie było, coś takiego jak miód nie zostałoby użyte. Zamiast tego możemy skutecznie wykorzystać zabezpieczenia poprzez zaciemnienie, aby spowolnić atakujących, o ile nie polegamy na nim w zakresie bezpieczeństwa naszej aplikacji.
ircmaxell