Pytanie:
Czy przechowywanie soli w tym samym polu co zaszyfrowane hasło jest bezpieczne / rozsądne?
PenumbraBrah
2018-04-06 19:26:27 UTC
view on stackexchange narkive permalink

Używając Argon2 do haszowania haseł w mojej aplikacji, zauważyłem, że generuje taki ciąg znaków (np. dla hasła „rabbit”):

  $ argon2i $ v = 19 $ m = 65536, t = 3, p = 1 $ YOtX2 // 7NoD / owm8RZ8llw == $ fPn4sPgkFAuBJo3M3UzcGss3dJysxLJdPdvojRF20ZE =  

Rozumiem, że wszystko przed p = jest parametry, treść p = to sól, a ostatnia część to zaszyfrowane hasło.

Czy dopuszczalne jest przechowywanie tego w jednym polu w bazie danych SQL ( varchar (99) w tym przypadku), czy też należy rozdzielić ciąg na jego części składowe? Czy powinienem przechowywać sól oddzielnie od zaszyfrowanego hasła i zachować parametry w kodzie?

[bardzo silnie powiązane] (https://security.stackexchange.com/questions/17421/how-to-store-salt)
Jeśli używasz [_pepper_] (https://security.stackexchange.com/questions/3272/password-hashing-add-salt-pepper-or-is-salt-enough), możesz przechowywać go poza bazą danych.
Funkcja PHP [password_hash] (http://php.net/manual/en/function.password-hash.php) również przechowuje sól z zahaszowanym ciągiem znaków (np .: `$ 2y $ 10 $ .vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a`)
„varchar (99)” wydaje się strasznie ciasny.Co się stanie, jeśli następna wersja biblioteki skrótów doda parametry lub wydłuży hash?Czy Twoja baza danych nie zawiera „varchar (MAX)” lub podobnego?
Siedem odpowiedzi:
Anders
2018-04-06 19:36:50 UTC
view on stackexchange narkive permalink

Powinieneś przechowywać go w jednym polu. Nie próbuj dzielić tego na części.

Wiem, że może się to wydawać nieco nieintuicyjne dla osób pochodzących z tła bazy danych, gdzie sposobem działania jest normalizacja danych, a używanie serializowanych ciągów jest uważane za brzydki hack. Jednak ze względów bezpieczeństwa ma to sens.

Dlaczego? Ponieważ najmniejszą jednostką, na której musi pracować indywidualny programista, jest ten pełny ciąg. To jest to, co aplikacja musi przekazać do biblioteki skrótów, aby sprawdzić, czy podane hasło jest poprawne, czy nie. Z punktu widzenia programistów, biblioteka skrótów może być czarną skrzynką i nie musi się martwić tym, co właściwie oznaczają te brzydkie części.

To dobrze, ponieważ większość programistów to niedoskonali ludzie (wiem , bo sam jestem jednym). Jeśli pozwolisz im rozebrać ten sznur, a następnie spróbujesz ponownie dopasować go do siebie, prawdopodobnie wszystko zepsują, na przykład dadzą wszystkim użytkownikom tę samą sól lub wcale.

Tylko przechowywanie parametrów w kodzie również jest złym pomysłem. Ponieważ procesory stają się szybsze, w przyszłości możesz chcieć zwiększyć współczynnik kosztów. Podczas fazy migracji różne hasła będą miały różne czynniki kosztowe. Będziesz więc potrzebować informacji na temat poziomu hasła o tym, jaki współczynnik kosztów został użyty do jego zaszyfrowania.

Wiele bibliotek kryptograficznych przyjmuje sekret i sól jako oddzielne parametry.Tylko z tego punktu widzenia rozsądne wydaje się przechowywanie wyciągu i soli / entropii na oddzielnych polach.Jeśli przechowujesz je osobno, nie musisz nawet używać jednakowej długości soli.Możesz wersjonować swoje algorytmy i obsługiwać więcej niż jeden naraz, co pozwala płynnie popychać użytkowników do nowszego, silniejszego algorytmu, nawet bez konieczności zmiany hasła, i tak dalej.
@Craig Wiele starszych bibliotek tak robi, ale powiedziałbym, że obecnie uważa się to za zły projekt.Jeśli chodzi o algorytmy wersjonowania, możesz to również zrobić z pełnym ciągiem znaków w jednej kolumnie.
Dlatego uwielbiam wymianę stosów.Każdego dnia uczę się czegoś, czego nie wiedziałem, czego nie wiedziałem.
Nie tylko z perspektywy praktyki bezpieczeństwa ma to sens.Nadal ma to sens z perspektywy normalizacji, biorąc pod uwagę powody, które przedstawiłeś.
Ma to również tę zaletę, że jest przyszłościowe;jeśli później zdecydujesz się zmienić parametry mieszania, stare skróty w bazie danych będą nadal działać _ (o ile używasz funkcji bibliotecznych do porównywania hashów, tak jak powinieneś to robić z Argon2, zamiast bezpośrednio porównywać ciągi hash) _
@Anders O jakiej bibliotece myślisz, która obsługuje wersjonowanie przechowywanego hasła za pomocą jednego pola hasła?Widzę, jak to działa, a podejście ma w sobie całkiem urok, ale nigdy nie widziałem takiego na wolności.
@Voo Dowolna biblioteka.Wszystkie potrzebne informacje - algorytm, parametry, sól - znajdują się w ciągu, który przechowujesz w jednej kolumnie.
@Anders To już nie jest czarna skrzynka, jeśli muszę zdefiniować własny format przechowywania oddzielnych części w jednym ciągu i samodzielnie konwertować krotkę (algorytm, hash, sól) i ciąg.Jeśli cokolwiek, co znacznie zwiększa prawdopodobieństwo wprowadzenia błędów.Myślałem, że cały pomysł polega na tym, aby programista nie musiał zajmować się oddzielnymi częściami?
@Voo Tak, chodzi o to, aby nie modyfikować ciągu.Nigdy tego nie rób.Nie chciałem tego sugerować.Myślę, że się nie rozumiemy.
@Voo spring-security w wersji 5 zmierza w tym kierunku: https://docs.spring.io/spring-security/site/docs/current/reference/html/core-services.html#pe-dpe.Jedyną funkcjonalnością, której mi brakuje, jest to, że biblioteka nie daje aplikacji możliwości migracji pola zaszyfrowanego hasła do domyślnego schematu kodowania (jeśli go nie używa)
Dla tych, którzy szukają przykładu biblioteki, która w przejrzysty sposób przechowuje wszystkie parametry, w tym algorytm, w jednym ciągu i umożliwia płynną aktualizację do silniejszych ustawień, sprawdź [funkcje PHP password_ *] (http://php.net/password), w tym przykłady [password_needs_rehash] (http://php.net/manual/en/function.password-needs-rehash.php).
@Voo To wersjonowanie musi zostać uruchomione przez programistę, ale dekodowanie i ponowne kodowanie jest całkowicie obsługiwane przez bibliotekę.
@Anders Interesowało mnie, jakie biblioteki faktycznie mają API, które działa z pojedynczym ciągiem znaków zamiast zwykłego potrójnego.W takim przypadku potrzebujesz jednak dodatkowej konfiguracji.Interfejs API wiosny jest dość interesujący.
@Voo Inną implementacją szyfrowania haseł, która przechowuje wszystkie trzy części jako jeden ciąg, jest [bcrypt] (https://en.wikipedia.org/wiki/Bcrypt) z implementacjami dla wielu języków.
Machavity
2018-04-06 22:34:26 UTC
view on stackexchange narkive permalink

Brakuje tego, że skróty działają na oryginalnych danych, bez oryginalnego ciągu. Kiedy chcesz zweryfikować ciąg pod kątem skrótu, bierzesz dostarczony ciąg oraz oryginalne dane skrótu (koszt, sól itp.) I generujesz nowy skrót. Jeśli nowy hash pasuje do starego, ciąg jest sprawdzany (innymi słowy, ciąg nigdy nie jest odszyfrowywany , jest ponownie szyfrowany ).

Sól nie pomaga w brutalnej sile. Sól jest istotną częścią haszu, podobnie jak kubki są częścią zamka. Jeśli wyjmiesz którykolwiek z nich, nikt nie będzie mógł go używać.

Oddzielanie pamięci nie ma sensu. W większości przypadków będziesz musiał ponownie złożyć ukończony hash, aby go zweryfikować. Dlatego wszystkie komponenty są domyślnie przechowywane w jednym poręcznym łańcuchu.

Wyjaśniłeś to o wiele bardziej elegancko niż ja, używając mniej słów.+1
Tak, rozdzielanie jest bezcelowe - nie możesz używać jednego bez drugiego, nigdy nie aktualizujesz jednego bez drugiego i mają identyczne wymagania bezpieczeństwa, więc traktuj sól + hasło jako jedną niepodzielną jednostkę do przechowywania.
keithRozario
2018-04-06 22:00:48 UTC
view on stackexchange narkive permalink

Tak, możesz przechowywać to w jednym polu, a wiele baz danych / aplikacji przechowuje sól + hash w jednym polu / pliku itp.

Najbardziej znany jest Linux (który nie jest DB), który przechowuje hash w pliku / etc / shadow przy użyciu formatu:

"$ id $ salt $ hashed", drukowalna forma skrótu hasła utworzona przez crypt (C) , gdzie „$ id” to używany algorytm. (W systemie GNU / Linux „1 $” oznacza MD5, „$ 2a $” to Blowfish, „$ 2y $” to Blowfish (poprawna obsługa 8-bitowych znaków), „5 $” to SHA-256, a „6 $ $” "to SHA-512, [4] inny Unix może mieć inne wartości, jak NetBSD.

(źródło: https://en.wikipedia.org/wiki/Passwd)

Sól nie ma być tajna (a przynajmniej nie bardziej tajna niż hash). Jej głównym celem jest znacznie utrudnianie ataków siłowych, ponieważ atakujący musi używać inna sól dla każdego użytkownika.

Ale twoje pytanie jest bardziej szczegółowe - ponieważ pytasz nie tylko o sole, ale także o parametry. Rzeczy takie jak algorytm haszujący, liczba iteracji i sól. W każdym przypadku, nie przechowuj tego w kodzie, nadal należą do bazy danych.

Wyobraź sobie, że masz grupę użytkowników i użyłeś SHA1 jako algorytmu haszującego. Więc pole bazy danych być czymś w rodzaju SHA1:SALT:HASH”.

Jeśli chcesz zaktualizować swoją bazę danych do BCRYPT, jak byś to zrobił?

Typi Oczywiście, można wdrożyć kod, aby po zalogowaniu się użytkownika zweryfikować hasło, a jeśli jest prawidłowe - ponownie zaszyfrować hasło przy użyciu nowszego algorytmu. Teraz pole dla użytkownika wygląda następująco: BCRYPT:SALT:HASH”.

Ale niektórzy użytkownicy korzystaliby z SHA1, a inni z BCRYPT, a ponieważ jest to na poziomie użytkownika, potrzebujesz parametrów, które mówią Twojemu kodowi, którzy użytkownicy mają być w bazie danych.

Krótko mówiąc, przechowywanie parametrów i hash w jednym polu jest OK, ale dzielenie ich z dowolnego powodu (wydajność, łatwiejszy kod itp.) również jest OK. Co nie jest w porządku, to przechowywanie tego w swoim kodzie :)

Troy Hunt niedawno opublikował podcast sugerujący, że zamiast przejść do BCRYPT w powyższy sposób, skuteczniej jest po prostu pobrać wszystkie skróty SHA1, które są obecnie w DB i zaszyfruj je za pomocą BCRYPT.

Skutecznie BCRYPT(SHA1(clear_password))

Gdy użytkownik loguje się na tobie

  BCRYPT (SHA1 (clear_password)) == <db_field>  

W ten sposób wszyscy na platformie zostaną zaktualizowani od razu i nie masz bazy danych z wieloma hashami formaty haseł. Bardzo czysty i bardzo ładny.

Myślę, że ten pomysł ma sens, ale mimo że wszyscy migrują na raz, nie jest to natychmiastowe. Jeśli nie chcesz zaakceptować przestojów w aplikacji (podczas ponownego zhaszowania wszystkich haseł), nadal będzie niewielka przerwa, w której niektórzy użytkownicy będą korzystać z BCRYPT, a niektórzy z SHA1, dlatego twoja baza danych powinna nadal przechowywać parametry algorytmu haszującego, a Twój kod zostanie wykonany na ich podstawie.

Znasz sprawę [Dlaczego nie powinniśmy tworzyć własnych?] (Https://security.stackexchange.com/q/18197/114527)?Czy `BCRYPT (SHA1 ())` * udowodniono *, że nie ma tego problemu?(Nie podałeś linku, abym mógł łatwo to sprawdzić, a określenie „ma doskonały sens” to nie to samo, co „to prawda”).
No cóż, zastrzegłem zdanie słowami „Myślę”, ma to sens :).Rozumiem, że jeśli BCRYPT działa, czyniąc brutalną siłę droższą, to niezależnie od tego, jakie dane wejściowe są, czy jest to SHA1, czy jawny tekst, nadal będzie droższe dla atakującego.BCRYPT (SHA1 ()) ma sens z punktu widzenia migracji.
Znalazłem również ten temat, który sugeruje inne przypadki użycia SHA-owania hasła przed BCRYPTOWANIEM.Ogólny konsensus w wątku był taki, że jest to w porządku, ale może powinniśmy rozpocząć osobne pytanie, jeśli nadal się nie zgadzasz https://security.stackexchange.com/questions/61595/is-it-good-practice-to-sha512-passwords-before-pass-them-to-bcrypt
@keithRozario „Intuicyjnie oczywiste jest, że BCRYPT (SHA1 (x)) jest co najmniej tak samo bezpieczny jak BCRYPT (x)” to nie to samo, co „istnieje dowód bezpieczeństwa, że ...”.Pierwsza zasada kryptografii: nigdy nie ufaj swojej intuicji, chyba że nazywasz się djb lub podobnie.
@MartinBonner jest poprawna.To * JEST * intuicyjne, ale jest też błędne.Załóżmy, że SHA1 jest uszkodzony.Symuluj to, zwracając 1 dla wszystkich wejść.BYCRYPT (SHA1 (x)) jest wyraźnie mniej bezpieczny niż BCRYPT (x) w tym scenariuszu, podobnie rozważmy SHA1 (BCRYPT (x)).W zależności od * sposobu * zerwania * SHA1 w łańcuchu, skróty * mogą * pozostać ważne.Ale to nigdy nie będzie bezpieczniejsze niż używanie tylko bezpieczniejszego z dwóch.Ponieważ idealnie wpływają na te same parametry w równaniu bezpieczeństwa.* Gdyby * mieli minimalne łańcuchy interakcji, mogłoby być przydatne, ale to dużo matematyki.Stąd * sprawdzone * @ AndrewMorton
@AndrewMorton Dobra dyskusja, ale nie jestem przekonany.Twój przykład symulacji zepsutego SHA1 przez zwrócenie 1 dla wszystkich danych wejściowych nie jest poprawny, to tak, jakby powiedzieć, że jeśli użytkownik wybierze 1 jako swoje hasło, to BCRYPT jest uszkodzony.Ale zaczynam kolejny wątek, ponieważ myślę, że to jest interesujące.
nowy wątek jest tutaj: https://security.stackexchange.com/questions/183358/how-secure-is-bcryptsha1password
@keithRozario Napisał to Black.
TTT
2018-04-07 00:27:25 UTC
view on stackexchange narkive permalink

Z punktu widzenia bezpieczeństwa nie ma znaczenia, czy sól i zaszyfrowane hasło są przechowywane w jednym polu, czy w oddzielnych polach, chociaż dla uproszczenia skłaniałbym się do jednego pola. Jedynym powodem ich rozdzielenia jest to, że kod aplikacji musi osobno przekazać sól i hasło do funkcji walidacji. Jeśli kod aplikacji wymaga tylko jednego połączonego ciągu, równie dobrze możesz go przechowywać w ten sposób.

Na przykład starsze członkostwo ASP.NET podzieliło skrót hasła i sól na dwa pola bazy danych, a nowsza ASP.NET Identity ma hash i sól w jednym polu bazy danych, a nowsze funkcje zostały zmodyfikowane tak, aby obsługiwały pojedynczy ciąg jako dane wejściowe i wyjściowe.

Andrew Morton
2018-04-08 00:36:49 UTC
view on stackexchange narkive permalink

Czy dopuszczalne jest przechowywanie tego w jednym polu w bazie danych SQL (w tym przypadku varchar (99))

Nie. Rozmiar danych może się kiedyś zmienić. Należy użyć pola varchar (MAX), chyba że specyfikacje określają, że rozmiar zawsze będzie wynosił dokładnie 99 i nie będzie żadnych odchyleń od tego nigdy . Niech baza danych zajmie się wymaganiami dotyczącymi przechowywania.

ArtisticPhoenix
2018-04-08 05:42:05 UTC
view on stackexchange narkive permalink

Aby wiedzieć, czy jest mniej lub bardziej bezpieczne, musimy zrozumieć, do czego służy sól.

Sól służy kilku celom (które przychodzą mi do głowy)

  1. Zapobiegaj atakom słownikowym

Atak słownikowy polega na użyciu słowa logicznego jako części hasła. Archetypem jest słowo password lub nawet P @ ssW0rd . Ludzie są niedoskonali i łatwiej jest im zapamiętać słowa niż przypadkowe ciągi liter i cyfr. Atak słownikowy polega na tym, aby skrócić ścieżkę, którą obrał atak brutalnej siły. Oczywiście, jeśli dodamy do niego losowy kawałek rzeczy, wtedy ten rodzaj ataku będzie niemożliwy lub bezcelowy i odsuwa ich z powrotem do brutalnego wymuszania całości.

Jeśli napastnik zna zastosowaną sól, musiałby edytować wszystkie pliki słowników dla każdego hasła, a to przy założeniu, że wie, w jaki sposób sól jest dodawana do oryginalnego hasła. Dużą zaletą listy słowników jest to, że bierzesz 1000 haseł i 1 milion słów ze słownika. Następnie przechodzisz między nimi, próbując uzyskać kilka dopasowań dla słabszych haseł. Tak więc edytowanie 1 miliona słów 1000 razy jest po prostu niepraktyczne.

  1. Zapobiegaj atakom typu Hash lub Rainbow Table.

A Tęczowa tabela to miejsce, w którym skróty są wstępnie obliczane i przechowywane w jakiejś bazie danych. Na przykład możesz wziąć MD5 i po prostu zacząć haszować losowe rzeczy i je zapisywać. Następnie, gdy chcesz złamać hasło, po prostu spójrz w tęczową tabelę.

Jeśli atakujący ma sól, musi ponownie skompilować tęczową tabelę dla każdej użytej soli. Zaletą tego ataku jest wcześniejsze skompilowanie danych i ich wielokrotne wykorzystywanie. To sprawia, że ​​z powrotem zmuszają się do brutalnego wymuszania hasła. Przez solenie i solenie wszystkich haseł w inny sposób oznacza to w zasadzie, że musisz ponownie obliczyć tęczową tabelę dla każdej soli. Dlatego ważne jest, aby przy każdym haśle używać różnych soli.

Podsumowanie

Żaden z tych powodów tak naprawdę nie polega na tym, że sól jest tajemnicą. Oczywiście wszystkie są mniej silne, jeśli napastnik zna sól. Ale dodatkowe informacje, które otrzymają, zawsze im pomogą. Więc nie powiedziałbym, żebym go reklamował, ale jest takie powiedzenie o bezpieczeństwie opartym na niejasności ....

Zrzeczenie się Nie jestem w żadnym wypadku ekspertem od kryptologii, ale to kilka głównych powodów, które przychodzą mi na myśl, kiedy myślę o solach.

Mam nadzieję, że to pomoże.

Mylisz się co do powodu trzeciego.Sól jest publiczna, więc atakujący może nadal korzystać ze wszystkich jednoznakowych haseł, wszystkich dwuznakowych haseł itp. * Jedyną * rzeczą, jaką robi sól, jest to, że atakujący musi pracować z jednym użytkownikiem na raz,
@MartinBonner - dobrze, usunąłem go ...
maggick
2018-04-06 19:36:48 UTC
view on stackexchange narkive permalink

Sól służy tylko do blokowania ataków na tęczowe tablice, dlatego sól może być przechowywana z zahaszowanym hasłem, tak jak ma to miejsce w najnowszym systemie GNU / Linux, gdzie sól jest przechowywana w / etc / shadow.

Nie jestem pewien, jak Twoja odpowiedź miałaby zastosowanie do różnych kolumn bazy danych?


To pytanie i odpowiedź zostało automatycznie przetłumaczone z języka angielskiego.Oryginalna treść jest dostępna na stackexchange, za co dziękujemy za licencję cc by-sa 3.0, w ramach której jest rozpowszechniana.
Loading...