Reset hasła to logowanie z pominięciem hasła, więc każda kontrola obecna w formularzu logowania musi zostać tu powtórzona albo świadomie zastąpiona innym mechanizmem. Jeśli ścieżka resetu jest słabsza niż ścieżka logowania, atakujący z niej skorzysta. OWASP Forgot Password Cheat Sheet nazywa tę funkcję „częstym źródłem podatności", a enumerację użytkowników podaje jako najlepiej znany przykład.
Dlaczego reset hasła jest słabym punktem
Udane logowanie tworzy sesję. Według wytycznych OWASP dotyczących zarządzania sesjami identyfikator uwierzytelnionej sesji jest tymczasowo równoważny najsilniejszej metodzie uwierzytelnienia, jakiej użyła aplikacja. Reset, który kończy się sesją albo hasłem wybranym przez atakującego, oddaje mu dokładnie to samo.
NIST SP 800-63B-4 wymaga na poziomie AAL2 wykazania posiadania i kontroli nad dwoma różnymi składnikami uwierzytelniania. Jeśli logowanie wymaga dwóch składników, reset oparty na jednym tokenie przesłanym e-mailem jest jednoskładnikowym obejściem tego zabezpieczenia. Fragment, na którym się opieramy, nie obejmuje odzyskiwania dostępu, ale pełny dokument zawiera sekcję o zarządzaniu zdarzeniami związanymi z uwierzytelniaczami (authenticator event management).
Nasza własna zasada brzmi tak: na koncie z zarejestrowanym drugim składnikiem poproś o ten składnik albo o zapisany kod odzyskiwania, zanim zaakceptujesz nowe hasło, i nigdy nie pozwalaj, by reset usuwał lub zastępował ten składnik.
Krok żądania resetu
Odpowiadaj tak samo niezależnie od tego, czy konto istnieje. Wystarczy komunikat: „Jeśli ten adres jest zarejestrowany, wysłaliśmy wiadomość e-mail".
Wyciekać może też czas odpowiedzi. Obsługa żądania, która kończy się wcześniej dla nieznanych adresów, a dla znanych wysyła wiadomość, ujawnia różnicę niezależnie od treści komunikatu. Wykonuj tę samą logikę dla każdego żądania albo przekaż wysyłkę wiadomości do zadania asynchronicznego.
Dodaj rate limiting per konto, CAPTCHA lub podobną kontrolę. Bez niej atakujący może wysyłać tysiące żądań resetu na godzinę dla jednego konta i zasypać skrzynkę e-mail lub SMS-y ofiary. Nie blokuj ani nie zmieniaj konta w reakcji na samo żądanie.
Token
OWASP stawia tokenowi lub kodowi cztery wymagania:
- jest generowany kryptograficznie bezpiecznym algorytmem losowym;
- jest wystarczająco długi, by odeprzeć brute force;
- jest bezpiecznie przechowywany;
- jest jednorazowy i wygasa po odpowiednim czasie.
Cheat sheet nie podaje wartości liczbowych dla długości ani czasu życia. Najbliższa liczba w źródłach pochodzi z wytycznych o sesjach: CSPRNG z entropią co najmniej 128 bitów, a najlepiej 160 bitów lub więcej. Zapis ten dotyczy tokenów sesji, a my stosujemy go do tokenów resetu. Jeśli chodzi o czas życia, wybierz krótką wartość, zapisz ją i testuj względem niej.
Sformułowanie „bezpiecznie przechowywany" można rozumieć rygorystycznie. Jeśli w Twoim modelu zagrożeń mieści się ujawnienie zawartości magazynu tokenów w trybie tylko do odczytu, wytyczne o sesjach opisują podział na identyfikator i sekret weryfikujący. Serwer przechowuje publiczny identyfikator służący do wyszukiwania oraz pełny skrót SHA-256 sekretu weryfikującego, a skróty porównuje w stałym czasie. Sam identyfikator nigdy nie może być uznany za dowód. Zastosowanie tego podejścia do tokenów resetu to nasza sugestia.
Dostarczaj token osobnym kanałem, e-mailem lub SMS-em, a nigdy w odpowiedzi wysyłanej do przeglądarki. Token w adresie URL to najprostszy projekt, ale wytyczne o sesjach ostrzegają, że identyfikatory w URL mogą wyciekać przez linki i logi, historię przeglądarki, zakładki, nagłówek Referer oraz wyszukiwarki. Wyeliminowanie treści zewnętrznych i linków wychodzących ze strony resetu zamyka tylko wyciek przez Referer. Aby zamknąć pozostałe, wymień token przy pierwszym żądaniu na krótkotrwały stan po stronie serwera, przekieruj na czysty adres URL i nie zapisuj tego pierwszego query stringa w logach dostępu.
Krok resetu
- Poproś użytkownika o dwukrotne wpisanie nowego hasła i sprawdź je według tej samej polityki co przy rejestracji.
- Hashuj je tą samą ścieżką kodu co każde inne hasło.
- Unieważnij wszystkie nieużyte tokeny resetu dla konta, gdy zmieni się hasło lub adres e-mail. W przeciwnym razie starsza wiadomość leżąca w skrzynce może posłużyć do ponownego zresetowania konta.
- Wyślij użytkownikowi e-mail z informacją, że hasło zostało zmienione. Nigdy nie umieszczaj hasła w wiadomości.
- Przekieruj użytkownika do zwykłego logowania zamiast logować go automatycznie. Automatyczne logowanie dodaje kod obsługi sesji, a z nim szansę na nowe podatności.
- Zakończ istniejące sesje albo przynajmniej zaoferuj taką możliwość.
Po podejrzeniu przejęcia konta aktywna sesja atakującego przetrwa zmianę hasła, jeśli jej nie zakończysz. My ustawilibyśmy unieważnianie sesji jako domyślne zachowanie.
MFA i przejęte konta
Samo zresetowanie hasła może nie przywrócić kontroli nad kontem. Atakujący może nadal mieć aktywną sesję albo mógł zmienić dane odzyskiwania lub metody MFA.
OWASP zaleca, by nie polegać wyłącznie na niedawno dodanych lub zmienionych danych odzyskiwania. Użyj niezależnych dowodów ustanowionych wcześniej, takich jak zapisane kody odzyskiwania, w kombinacji spełniającej wymagania dotyczące poziomu pewności dla danego konta. Resetowanie MFA ma osobną sekcję w OWASP Multifactor Authentication Cheat Sheet, więc prowadź ten proces oddzielnie od przepływu resetu hasła.
OWASP Authentication Cheat Sheet omawia także zmianę zarejestrowanego adresu e-mail. Ma to znaczenie, ponieważ zmieniony adres przekierowuje wszystkie przyszłe resety.
Testowanie przepływu
| Test | Jak wygląda zaliczenie |
|---|---|
| Istniejący i nieistniejący adres | Ten sam komunikat i kod statusu |
| Skryptowa seria żądań na adres | Mediany czasów odpowiedzi są zgodne |
| Powtarzane żądania dla jednego konta | Uruchamia się rate limit lub CAPTCHA |
| Żądanie resetu, a następnie logowanie | Konto nie jest zablokowane ani zmienione |
| Token użyty dwukrotnie lub po wygaśnięciu | Próba kończy się niepowodzeniem |
| Stary token po zmianie hasła lub e-maila | Próba kończy się niepowodzeniem |
| Strona resetu z tokenem w URL | Brak żądań do stron trzecich i linków wychodzących |
| Reset przy otwartej starej sesji | Stara sesja zostaje zakończona |
| Zarejestrowany drugi składnik, tylko token z e-maila (nasza zasada) | Reset zostaje odrzucony |
| Końcowa odpowiedź i wiadomość e-mail | Brak automatycznego logowania, brak hasła w wiadomości |
W wierszu dotyczącym czasu porównuj mediany i rozrzut z wielu przebiegów. Ten test powinien wchodzić w skład każdego testu penetracyjnego przepływu uwierzytelniania.
Od czego zacząć
- Wielokrotnie zażądaj resetu dla istniejącego i nieistniejącego konta. Porównaj komunikat, kod statusu i czas odpowiedzi.
- Przeczytaj kod generatora tokenów. Upewnij się, że używa CSPRNG, uczyń tokeny jednorazowymi i ustaw czas życia, który potrafisz podać w minutach.
- Dodaj rate limiting per konto lub CAPTCHA do endpointu żądania resetu i sprawdź, że samo żądanie nigdy nie blokuje ani nie modyfikuje konta.
- Spraw, by reset kończył inne sesje, unieważniał nieużyte tokeny i wysyłał e-mail z powiadomieniem bez hasła. Sprawdź, że strona resetu nie ładuje niczego od stron trzecich.
- Weź konto testowe z włączonym MFA i spróbuj je zresetować wyłącznie za pomocą tokenu z e-maila. Upewnij się, że reset zostaje odrzucony.
- Sprawdź, kto może zresetować lub usunąć drugi składnik, jakie dowody musi przedstawić i czy proces odzyskiwania traktuje niedawno zmienione dane jako niezaufane.
