Reflected XSS (Non-Persistent)
Este apartado explica el funcionamiento del XSS reflejado, un tipo de XSS no persistente, cómo detectarlo y cómo se explota realmente contra víctimas.
🧠 XSS No Persistente (Non-Persistent)
Existen dos tipos de XSS no persistente:
| Tipo | Dónde se procesa |
|---|---|
| 🔁 Reflected XSS | Servidor back-end |
| 🧬 DOM-based XSS | Navegador (lado cliente) |
-
No se guarda en la base de datos
-
No persiste al recargar
-
Afecta solo al usuario objetivo
🔁 ¿Qué es Reflected XSS?
Ocurre cuando:
-
La entrada del usuario llega al servidor
-
El servidor la devuelve en la respuesta
-
No se filtra ni se escapa correctamente
-
El navegador ejecuta el JavaScript
📌 Suele aparecer en:
-
Mensajes de error
-
Resultados de búsqueda
-
Mensajes de confirmación
-
Formularios inválidos
🧪 Entorno vulnerable de práctica
Aplicación tipo To-Do List, similar al ejemplo anterior, pero con validación fallida.
Accedemos a:
http://<IP>:<PUERTO>/
🖥️ Interfaz:
-
Campo “Your task”
-
Botón Add
-
Mensaje de error al fallar
Ejemplo de entrada normal:
test
📌 Mensaje devuelto por el servidor:

Task 'test' could not be added.
➡️ Nuestra entrada se refleja directamente en el mensaje.
🧨 Prueba de XSS reflejado
Probamos la misma carga básica:
<script>alert(window.origin)</script>
La enviamos pulsando Add.
📸 Resultado:

-
Aparece una alerta
-
Muestra el dominio vulnerable
El código JavaScript se ejecutó → XSS reflejado confirmado
🔎 Análisis del comportamiento
Después del payload, el mensaje ahora muestra:

Task '' could not be added.
📌 ¿Por qué aparecen comillas vacías?
-
El navegador no renderiza
<script>como texto -
Ejecuta el código
-
El HTML visible queda vacío
📄 Confirmación en el código fuente
Al ver el código fuente (CTRL + U):

<div style="padding-left:25px">
Task '<script>alert(window.origin)</script>' could not be added.
</div>
La carga está:
-
Procesada por el servidor
-
Devuelta sin sanitizar
-
Ejecutada por el navegador
🔄 ¿Por qué NO es persistente?
-
Si recargamos la página
-
O entramos de nuevo sin el payload
👉 El mensaje desaparece
👉 El script no se ejecuta
Esto confirma que es:
🎯 Entonces… ¿cómo se ataca a una víctima?
Si no es persistente, ¿cómo afecta a otros usuarios?
La respuesta está en el tipo de petición HTTP.
🌐 Análisis de la petición HTTP
Abrimos las DevTools del navegador:
CTRL + Shift + I → Network
Repetimos la prueba y observamos:
📌 La petición es:
GET

Las peticiones GET envían los datos en la URL
🔗 Explotación real (enlace malicioso)
Si el payload viaja en la URL, el ataque consiste en:
Ejemplo conceptual:
http://<IP>:<PUERTO>/?task=<script>alert(window.origin)</script>
📌 Cuando la víctima:
-
Hace clic en el enlace
-
Visita la URL
-
Abre un email / mensaje / chat
👉 El navegador ejecuta el payload
🎣 Vectores comunes de ataque
-
Phishing
-
Emails
-
Chats
-
Redes sociales
-
Enlaces acortados
-
QR maliciosos
🧠 Comparación rápida: Stored vs Reflected
| Característica | Stored XSS | Reflected XSS |
|---|---|---|
| Persistencia | ✅ Sí | ❌ No |
| Afecta a múltiples usuarios | ✅ | ❌ |
| Requiere interacción | ❌ | ✅ (clic) |
| Vector típico | Formulario | URL |
| Impacto | Muy alto | Medio |
🧠 Resumen final
-
No se almacena en la base de datos
-
Se ejecuta solo al visitar una URL maliciosa
-
Depende del servidor backend
-
Muy común en mensajes de error
-
Usado principalmente en ataques de phishing