SANDBOX DE INYECCIÓN XSS
Un atacante te manda este enlace por email o chat. El buscador simplemente repite tu propio texto en la respuesta — sin guardarlo en ningún sitio.
Publicas un comentario que queda guardado. A partir de ahora, todo el que visite la página lo ve — y lo ejecuta.
Aquí no hay servidor de por medio: el propio JavaScript del navegador lee el trozo de la URL después del # y lo escribe directo en la página.
HTML que se inserta en la página:
🎬 EJEMPLOS PARA PROBAR
📖 CHULETA RÁPIDA
🔁 Reflejado
El payload viaja en la URL (o un formulario) y el servidor lo devuelve al instante, sin guardarlo. Solo afecta a quien haga clic en el enlace envenenado — hace falta ingeniería social para repartirlo.
💾 Almacenado
El payload queda guardado (un comentario, una reseña, un perfil...) y se ejecuta para cada visitante que cargue esa página después, sin que nadie tenga que hacer clic en nada. El más peligroso de los tres.
🧩 DOM-based
Ni el servidor llega a ver el payload: el JavaScript del propio navegador lee datos de la URL (o de otro sitio del lado cliente) y los mete en la página. Un filtro en el backend no serviría de nada aquí.
La sorpresa técnica: <script> no funciona así como así
Cuando insertas HTML con innerHTML, los navegadores ignoran las etiquetas <script> a propósito — pruébalo arriba. Por eso los ataques reales casi siempre usan manejadores de eventos: onerror, onload, onclick...
La defensa real: escapar en el punto de salida
Convertir < en < (y similares) antes de insertar el dato hace que el navegador lo trate como texto, nunca como estructura — el mismo principio que los parámetros en GHOSTSQLI, aplicado a HTML en vez de a SQL.
CSP: la red de seguridad de más
Una Content-Security-Policy con script-src 'none' (o restringido a orígenes concretos) bloquea la ejecución aunque el escapado falle en algún sitio — pruébalo arriba con el escapado desactivado.
Los frameworks modernos ayudan (pero no son magia)
React, Vue y Angular escapan por defecto — por eso XSS es menos frecuente hoy que hace una década. Pero dangerouslySetInnerHTML, v-html o [innerHTML] siguen abriendo exactamente este mismo agujero si se usan con datos no confiables.
Referencia
XSS (Cross-Site Scripting) sigue dentro de la categoría A03:2021 del OWASP Top 10 — Injection, la misma familia que GHOSTSQLI. El fallo de fondo es idéntico: mezclar datos y código sin una frontera clara entre ambos.