Pytanie Preferowana metoda przechowywania haseł w bazie danych


Jaka jest twoja preferowana metoda / typ danych do przechowywania haseł w bazie danych (najlepiej SQL Server 2005). Sposób, w jaki robiłem to w kilku naszych aplikacjach, polega na pierwszym użyciu bibliotek szyfrowania .NET, a następnie zapisaniu ich w bazie danych jako binarne (16). Czy jest to preferowana metoda, czy powinienem używać innego typu danych lub przydzielać więcej miejsca niż 16?


76
2018-03-05 17:10


pochodzenie


Mam przeczucie, że to może być dupek, ale to, co uważałem za duplikat, okazało się być związane z rzeczywistymi logami DB, a nie tylko przechowywaniem loginu aplikacji / witryny. - TheTXI
Czy mógłbyś wyjaśnić swoje pytanie, aby wyjaśnić, czy używasz funkcji "szyfrowania" czy "hashowania"? Myślę, że masz na myśli to ostatnie, ale różnica jest bardzo znacząca. - ine


Odpowiedzi:


Przechowuję solenizowany hash równoważny hasłu w bazie danych i nigdy nie wpisuję samego hasła, a następnie zawsze porównuję wartość skrótu z wygenerowanym hasłem użytkownika.

Jest zbyt niebezpieczne, aby kiedykolwiek przechowywać dosłowne dane w dowolnym miejscu. To sprawia, że ​​odzyskanie danych jest niemożliwe, ale gdy ktoś zapomni lub straci hasło, możesz przeprowadzić kilka kontroli i utworzyć nowe hasło.


80
2018-03-05 17:12



@Quinton: To jest to, co robię. Z bibliotekami szyfrowania .net będzie mieszać hasło, a następnie przekazuję je do DB i przechowuję jako plik binarny. Mogę porównywać hasła tylko poprzez hashowanie użytkownika i porównywanie go z tym, co jest przechowywane. - TheTXI
Wygląda na to, że jesteś na dobrej drodze. - Quintin Robinson
Polecam jbcrypt, jeśli pracujesz z java. Niezwykle prosty w użyciu - Jens Schauder
Przechowujemy również solone hasła. W naszym przypadku konwertujemy 160-bitowy na base64 i przechowujemy go w varcharze - to po prostu ułatwia sprawę (łańcuchy są łatwiejsze do odczytu / zapisu / oglądania). Oprócz globalnej soli przygotowujemy ją za pomocą identyfikatora użytkownika (sid lub guid), aby dwaj użytkownicy o tym samym haśle nie mieli tego samego skrótu. To sprawia, że ​​ataki słownikowe są trudniejsze (więcej kosztu procesora) i uniemożliwiają wykrycie hasła dla wielu jednocześnie, gdy wszyscy wybierają to samo hasło. - Ian Boyd
@IanBoyd, na wypadek, gdybyś nie zmienił metody soli, robisz to źle. Powinien być losowy, z wystarczającą entropią i specyficznym dla użytkownika, w którym to przypadku przestrzegasz tylko tego ostatniego. - Francisco Presencia


Preferowana metoda: nigdy nie przechowuj haseł w swoim DB. Tylko jego hasze. Dodaj sól do smaku.


47
2018-03-05 17:16



mod, musiał to zrobić, tylko na żart solny;) - Jakub
uśmiechnąłem się również do niego. - Ian Boyd


Robię to samo, co opisałeś, z wyjątkiem tego, że jest on przechowywany jako ciąg. I Base64 koduje zaszyfrowaną wartość binarną. Ilość miejsca do przydzielenia zależy od algorytmu szyfrowania / siły szyfrowania.

Myślę, że robisz to dobrze (biorąc pod uwagę, że używasz a Sól).


15
2018-03-05 17:15



+1 za odpowiedź na prawdziwe pytanie tutaj. - erickson


Ponieważ wynikiem funkcji mieszającej jest seria bajtów w zakresie od 0 do 255 (lub od -128 do 127, w zależności od podpisanej wartości twojego 8-bitowego typu danych), przechowywanie jej jako surowego pola binarnego ma największy sens , ponieważ jest to najbardziej kompaktowa reprezentacja i nie wymaga żadnych dodatkowych kroków kodowania i dekodowania.

Niektóre bazy danych lub sterowniki nie mają dużego wsparcia dla typów danych binarnych, a czasami programiści nie są dostatecznie zaznajomieni z nimi, aby czuć się komfortowo. W takim przypadku użycie kodowania binarnego do tekstu, takiego jak Base-64 lub Base-85, i zapisywanie wynikowego tekstu w polu znaku jest dopuszczalne.

Rozmiar wymaganego pola jest określony przez funkcję skrótu, której używasz. MD5 zawsze wysyła 16 bajtów, SHA-1 zawsze daje 20 bajtów. Po wybraniu funkcji skrótu zazwyczaj utkniesz w niej, ponieważ zmiana wymaga zresetowania wszystkich istniejących haseł. Używanie pola o zmiennym rozmiarze nic nie kupi.


Jeśli chodzi o "najlepszy" sposób na wykonanie skrótu, próbowałem udzielić wielu odpowiedzi na inne pytania SO dotyczące tego tematu:


8
2018-03-05 17:22



Jeśli przeczytasz moje pytanie nieco bliżej, zobaczysz, że skupiam się bardziej na faktycznym przechowywaniu pod względem typu danych i miejsca przydzielonego dla tego pola. - TheTXI
Ale +1 za dostarczanie dodatkowych informacji innym, którzy mogą przyjść później. - TheTXI
Tak jest. Wygląda na to, że nie jestem jedyny, który tęskni;) - erickson


  1. przechowuj hash solonego hasła, na przykład bcrypt (nounce + pwd). Możesz preferować bcrypt na SHA1 lub MD5, ponieważ może on być dostrojony do intensywnego procesora, przez co atak z użyciem siły brutalnej będzie dłuższy.
  2. dodaj captcha do formularza logowania po kilku błędach logowania (aby uniknąć ataków typu brute-force)
  3. jeśli twoja aplikacja ma link "nie pamiętam hasła", upewnij się, że nie wysyła nowego hasła przez e-mail, ale zamiast tego powinien wysłać link do strony (zabezpieczonej) pozwalającej użytkownikowi na zdefiniowanie nowego hasła (prawdopodobnie tylko po potwierdzeniu niektórych danych osobowych, na przykład daty urodzenia użytkownika. Ponadto, jeśli aplikacja umożliwia użytkownikowi zdefiniowanie nowego hasła, upewnij się, że użytkownik wymaga potwierdzenia bieżącego hasła.
  4. i oczywiście zabezpiecz formularz logowania (zazwyczaj z HTTPS) i same serwery

Dzięki tym środkom hasła użytkownika będą dość dobrze chronione przed:

  1. => ataki słownikowe offline
  2. => ataki słownikowe na żywo
  3. => ataki typu "odmowa usługi"
  4. => wszelkiego rodzaju ataki!

8
2018-03-05 17:51



Wszystkie te środki można szybko wdrożyć i pakuje się w niecały wysiłek przy minimalnym wysiłku! +1 =) - Luke Antins
Czy ataki DOS są związane z zabezpieczeniem hasłem? - Arj
@ a12jun: jeśli masz link "nie pamiętasz hasła" na swojej stronie internetowej za pomocą prostego "logowania" i "proszę wygeneruj nowe hasło i wyślij mi je pocztą e-mail", wtedy każdy, kto zna twój login, może zmusić cię do zmiany hasła. Jeśli automatyzuje to uruchamianie co 10 sekund, może odmówić Ci dostępu do konta. Jeśli uruchomi to przeciwko tysiącom użytkowników, prawdopodobnie może sprawić, że wielu z nich nie spodoba się twojemu serwisowi. Wytyczna nr 3 może cię chronić przed tym, to właśnie miałem na myśli (nie było to zbyt jasne, muszę przyznać). Bezpieczeństwo = poufność, uczciwość, Dostępność. - MiniQuark
@MiniQuark: Dobre wytłumaczenie, nie pomyślałem o tym! - Arj


Używam skrótu sha nazwy użytkownika, guid w konfiguracji sieci i hasła, przechowywanego jako varchar (40). Jeśli chcą użyć brutalnej siły / słownika, będą musieli włamać się do serwera sieciowego również dla GUID. Nazwa użytkownika łamie się, tworząc tęczową tabelę w całej bazie danych, jeśli znajdzie hasło. Jeśli użytkownik chce zmienić swoją nazwę użytkownika, po prostu resetuję hasło w tym samym czasie.

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
    username.ToLower().Trim(),
    ConfigurationManager.AppSettings("salt"),
    password
);

4
2018-03-05 23:05



użyłem nazwy użytkownika jako dodanej soli. Ale nie mogliśmy zmienić nazwy użytkownika. Przełączyliśmy się na używanie soli z identyfikatorem użytkownika, guid, sid lub czymś innym kluczem zastępczym. - Ian Boyd
tru, dobry telefon. w ten sposób nie musisz resetować hasła podczas zmiany nazwy użytkownika - Shawn


Prosty hash hasła, a nawet (sól + hasło) nie jest na ogół wystarczający.

widzieć:

http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/

i

http://gom-jabbar.org/articles/2008/12/03/why-you-bould-use-bcrypt-to-store-your-passwords

Obie polecają algorytmy bcrypt. Bezpłatne implementacje można znaleźć w Internecie dla najpopularniejszych języków.


3
2018-03-05 18:05



Świetne linki, które wykraczają poza powierzchowne problemy bezpieczeństwa. Czy dla celowo wolnych algorytmów ważne jest, aby hashy obliczano po stronie klienta, aby nie przeciążać (prawdopodobnie już dość zajęty) serwera? - cheduardo
Nie całkiem. Celem jest po prostu uczynienie go "Nieco" wolniejszym. Po prostu dać ci pomysł. Mogę zaszyfrować SHA1 około 200 kilobajtów na sekundę w systemie czterordzeniowym. Wątpię, aby ktokolwiek potrzebował obsługiwać 200K równoczesnych logowań w ciągu sekundy ... Więc użyjesz funkcji takiej jak PBKDF2 lub bcrypt, aby zwolnić ją, aby powiedzieć tylko 100 ha na sekundę (zwiększa linię czasu brutalnej siły o współczynnik 200). - Gerald Davis


Możesz użyć wielu skrótów w bazie danych, wymaga to tylko odrobiny dodatkowego wysiłku. Warto jednak, jeśli uważasz, że istnieje największa szansa na wsparcie dodatkowych formatów w przyszłości. Często używam haseł takich jak

{hashId} $ {salt} $ {zakodowane hasło}

gdzie "hashId" to tylko pewna liczba, której wewnętrznie używam, aby rozpoznać, że np. używam SHA1 z określonym wzorem hash; "sól" jest losową solą kodowaną przez zasadę 64; a "hashed password" to hash zakodowany w base64. Jeśli musisz migrować hashy, możesz przechwytywać osoby ze starym formatem hasła i zmieniać je przy następnym logowaniu.

Jak wspomnieli inni, chcesz zachować ostrożność w swoich hasach, ponieważ łatwo jest zrobić coś, co nie jest naprawdę bezpieczne, np. H (sól, hasło) jest znacznie słabsze niż H (hasło, sól), ale w tym samym czasie chcesz zrównoważyć wysiłek włożony do tego z wartością zawartości witryny. Często używam H (H (hasło, sól), hasło).

Wreszcie, koszt używania haseł zakodowanych w base64 jest niewielki w porównaniu z korzyściami płynącymi z możliwości korzystania z różnych narzędzi, które oczekują danych tekstowych. Tak, powinny być bardziej elastyczne, ale czy jesteś gotowy powiedzieć swojemu szefowi, że nie może użyć swojego ulubionego narzędzia innej firmy, ponieważ chcesz zapisać kilka bajtów na rekord? :-)

Edytowane w celu dodania jeszcze jednego komentarza: gdybym zasugerował celowe użycie algorytmu, który spaliłby nawet 1/10 sekundy haszującego każde hasło, miałbym szczęście, żebym po prostu wyśmiał się z biura mojego szefa. (Nie miał tyle szczęścia, zechciałby napisać coś na temat mojej następnej rocznej recenzji). Nagrywanie tego czasu nie stanowi problemu, gdy masz dziesiątki, a nawet setki użytkowników. Jeśli przesyłasz 100 tys. Użytkowników, zwykle będziesz mieć wiele osób logujących się w tym samym czasie. Potrzebujesz czegoś szybkiego i mocnego, nie powolnego i mocnego. "Ale co z informacjami o karcie kredytowej?" jest w najlepszym wypadku nieszczęśliwy, ponieważ przechowywane informacje o karcie kredytowej nie powinny znajdować się w pobliżu twojej zwykłej bazy danych, i powinny być zaszyfrowane przez aplikację, a nie przez indywidualnych użytkowników.


3
2018-03-23 16:17



Nie ma czegoś tak szybkiego i silnego, jeśli chodzi o mieszanie. Przepraszam. Jeśli jest to szybkie dla ciebie, jest szybkie dla napastnika o brutalnej sile. Używanie funkcji wyprowadzania klucza jest prawidłową metodą wzmocnienia haseł. - Gerald Davis


Jeśli pracujesz z ASP.Net, możesz użyć wbudowanego interfejsu API.

Obsługuje wiele typów opcji przechowywania, w tym; jeden sposób hash, dwukierunkowe szyfrowanie, md5 + sól. http://www.asp.net/learn/security po więcej informacji.

Jeśli nie potrzebujesz niczego zbyt fantazyjnego, jest to świetne rozwiązanie dla stron internetowych.

Jeśli nie korzystasz z ASP.Net, tutaj jest dobry link do kilku artykułów od 4guys i codeproject

http://aspnet.4guysfromrolla.com/articles/081705-1.aspx http://aspnet.4guysfromrolla.com/articles/103002-1.aspx http://www.codeproject.com/KB/security/SimpleEncryption.aspx


2
2018-03-05 18:24





Ponieważ twoje pytanie dotyczy metody i rozmiaru pamięci masowej, odpowiem na to.

Typem pamięci może być binarna lub tekstowa reprezentacja (podstawowa 64 jest najbardziej rozpowszechniona). Plik binarny jest mniejszy, ale łatwiej jest pracować z tekstem. Jeśli robisz solenie dla użytkownika (inna ilość soli na hasło), łatwiej jest przechowywać sól + hash jako pojedynczy połączony ciąg.

Rozmiar jest zależny od algorytmu mieszania. Wyjście MD5 ma zawsze 16 bajtów, SHA1 ma zawsze 20 bajtów. SHA-256 i SHA-512 to odpowiednio 32 i 64 bajty. Jeśli korzystasz z kodowania tekstu, będziesz potrzebował nieco więcej pamięci w zależności od metody kodowania. Używam Base64, ponieważ pamięć jest stosunkowo tania. Base64 będzie wymagał około 33% większego pola.

Jeśli masz solenie dla użytkownika, będziesz potrzebował miejsca na haszowanie. Łączenie w całość 64-bitowej soli + SHA1 hash (160 bitów) kodowanej base64 zajmuje 40 znaków, więc zapisuję je jako char (40).

Na koniec, jeśli chcesz zrobić to dobrze, nie powinieneś używać pojedynczego skrótu, ale funkcję wyprowadzania klucza, taką jak RBKDF2. Skórki SHA1 i MD5 są szalenie szybkie. Nawet aplikacja z pojedynczym wątkiem może mieszać od 30 000 do 50 000 haseł na sekundę, czyli do 200 000 haseł na sekundę na czterordzeniowym komputerze. Procesory graficzne mogą mieszać od 100x do 1000x tyle haseł na sekundę. Przy takich prędkościach ataki brute force stają się dopuszczalną metodą włamań. RBKDF2 pozwala określić liczbę iteracji, aby dostroić sposób "powolnego" mieszania. Nie chodzi o to, aby system był na kolanach, ale aby wybrać liczbę iteracji, aby ograniczyć górny limit szybkości mieszania (powiedzmy 500 ha na sekundę). Przyszłością metody proof byłoby włączenie liczby iteracji w polu hasła (iteracje + sól + hash). Pozwoli to na zwiększenie liczby powtórzeń w przyszłości, aby dotrzymać kroku mocniejszym procesorom. Aby być jeszcze bardziej elastycznym, użyj varchar, aby umożliwić potencjalnie większe / alternatywne skróty w przyszłości.

Implementacja .Net to RFC2892DeriveBytes http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx


2
2017-11-16 23:22