![]() |
![]() |
![]() ![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 1 012 Pomógł: 109 Dołączył: 26.09.2003 Skąd: nexis.pl Ostrzeżenie: (0%) ![]() ![]() |
Zwykle, dla bezpieczeństwa, trzymamy w bazie danych skrót hasła, utworzony za pomocą md5() bądź sha1(). Z myślą o tęczowych tablicach dopisujemy zwykle dodatkowo tzw. sól, która jest trzymana poza bazą danych, zwykle na serwerze.
Chciałbym jednak zwiększyć bezpieczeństwo również po stronie użytkownika i zastosować mechanizm znany z banków internetowych, czyli odpytywanie użytkownika o wybrane znaki hasła. Aby zastosować taki mechanizm jestem jednak zmuszony zapamiętać każdy znak hasła osobno. Powiedzmy, że w tym celu narzucę maksymalną długość hasła na 16 znaków i stworzę w tabeli bazy danych 16 dodatkowych pól (po 1 dla każdego znaku). Jak ma się jednak w/w sposób do tej sytuacji? Sam skrót to praktycznie żadne zabezpieczenie. Zastosowanie soli już bardziej, ale jest to wciąż bardzo słaby mechanizm. Co zrobić? |
|
|
![]() |
![]()
Post
#2
|
|
Grupa: Moderatorzy Postów: 4 362 Pomógł: 714 Dołączył: 12.02.2009 Skąd: Jak się położę tak leżę :D ![]() |
Wczoraj w chwili przerwy przejrzałem nasze wypowiedzi i zauważyłem jedną rzecz. Algorytm nad jakimi dumamy ma jedną, poważną (moim zdaniem) wadę. Działa jak należy gdy wywołamy procedurę zmiany hasła jawnie (tworzenie nowego przez usera czy "zapomniane hasło"). Jednak przy zmianie czegoś w algorytmie (tokeny czasowe, zmiana soli itp. ) będziemy leżeli i kwiczeli. Przy zmianie nikt nic nie będzie mógł autoryzować lub w skrajnym przypadku (jeśli prośba o podanie znaku z pozycji określonej wyskoczy przy logowaniu) nie zaloguje się. Błąd wynika z tego, że hashe porównawcze są generowane na podstawie istniejącego hasła. Każda więc zmiana pociąga za sobą konieczność generowania nowych hashy a więc i wymusza znajomość jawnej postaci hasła. Stąd też myślę, że konieczne byłoby uniezależnienie się algorytmu od tego typu luki. Moim zdaniem konieczne dlatego jest odwzorowanie hasła na inny ciąg. I tutaj pojawia się poważny problem. Jak to zrobić, by zmiana hasła lub zmiana w algorytmie nie pociągała za sobą konieczności poznania postaci jawnej hasła usera? W swoim algorytmie zauważyłem inny błąd logiczny wczoraj. Działa on gdy otrzymuje pozycję znaku wpisanego przez usera. Tylko skąd ma tak naprawdę wiedzieć czy znak, który wpisał user, jest oryginalnie w haśle czy nie, a jeśli tak to na jakiej tak naprawdę pozycji? Brakuje mu więc funkcji transkodowania znaku na pozycje w haśle i powinien zostać zmodyfikowany by mógł być prawidłowy. Dlatego w tej chwili jeśli chcemy faktycznie zastanowić się jak zrobić tę autoryzację musimy rozwiązać problem niezależności hasła od algorytmu. Lub inaczej to ujmując, znaleźć sposób na to, by móc zmieniać w dowolnej chwili hashe bez konieczności poznania jawnej postaci hasła. Dopóki więc Twój nie znajdzie metody na uniezależnienie się hasła od algorytmu, a w moim nie znajdzie się funkcja potrafiąca rozpoznać pozycję w haśle znaku podanego przez usera to oba, moim zdaniem, nie powinny być brane pod uwagę, ze względow bezpieczeństwa. Dlatego teraz skupmy się nie na otoczce jak sprawić by kod był nie do złamania, ale nad tym jak w sposób nie wymagający poznania hasła wprowadzić do algorytmu możliwość generowania skrótów gdy zmieniamy coś w środku. Innymi słowy musimy znaleźć "zastępcę" hasła, który będzie wyjściowym w razie zmian.
Jak to widzę by ominąć problem? Zmiana hasła pociąga za sobą utworzenie sha2 (lub innego, którego jeszcze nie "łamią" ) każdej litery w haśle i wrzucenie gdzieś do bazy a potem postępowanie według algorytmu jakby nigdy nic. W razie konieczności zmiany czegoś w algorytmie generujemy nowe hashe dla usera na podstawie hasha każdej z liter nie bacząc wcale na znajomość hasła. A jak będzie ze sprawdzeniem? W zasadzie nawet wystarczyło by sprawdzenie czy hash litery przesłanej pokrywa się z hashem generowanym. Wniosek: Nie ma sensu kodować jakichś zmian wielkich bo algorytm nie będzie nigdy w pełni niezależny od hasła i złamanie go będzie miało punkt krytyczny w miejscu zapisu znaków hasła, jeśli zechcemy się uniezależnić od jego znajomości co automatycznie poddaje w wątpliwość sens pisania niesamowicie skomplikowanych algorytmów. Bo po co mam przerzucać literę przez cały kod z hashami, tokenami i obciążać bazę generowaniem ich dla ogromu użytkowników co jakiś czas, skoro porównanie może nastąpić zaraz po użyciu funkcji hashującej znak na konkretnej pozycji? Czyli de facto wracamy do punktu początkowego. By to unaocznić rozrysuję drogę: Zapis do bazy przy zmianie (tworzeniu) hasła: Litera hasła -> hash litery -> algorytm, token i sole -> hash litery po algorytmie Zmiana algorytmu, soli lub tokena: hash litery -> zmieniony algorytm, sole lub token -> nowy hash liter Porównanie: user podaje literę hasła -> algorytm, token i sole -> wyliczony hash -> porównanie z "hash litery po algorytmie" Tyle że takie działanie jest kompletnie bezsensowne z prostej przyczyny: wystarczy złamać "hash litery" i algorytm leży. Inna sprawa, że wystarczy sprawdzić czy "hash litery" i "user podaje literę hasła" + funkcja hashująca dają to samo (IMG:style_emoticons/default/dry.gif) Czyli sens algorytmu można rozwalić o kant d... i zawsze musimy znać jawna postać hasła lub hash jego liter gdy zamierzamy robić tokeny. Jest to więc bardziej sztuka dla sztuki niż poważne podejście do bezpieczeństwa.<br>Błagam, niech mnie ktoś wyprowadzi z błędu (IMG:style_emoticons/default/winksmiley.jpg) |
|
|
![]() ![]() |
![]() |
Aktualny czas: 11.10.2025 - 07:27 |