Reflected XSS surge cuando una aplicación recibe datos en una solicitud HTTP e incluye esos datos en la respuesta inmediata de forma no segura.
Impacto del ataque de un Reflected XSS
Si un atacante puede controlar un script que se ejecuta en el navegador de la víctima, normalmente puede comprometer completamente a ese usuario:
Realizar cualquier acción dentro de la aplicación que el usuario pueda realizar.
Ver cualquier información que el usuario pueda ver.
Modificar cualquier información que el usuario pueda modificar.
Iniciar interacciones con otros usuarios de la aplicación, incluidos ataques maliciosos, que parecerán ser originados desde el usuario víctima.
Existen múltiples métodos para inducir a un usuario a realizar una solicitud que controlamos, como las siguientes:
Colocar enlaces en un sitio web controlado por el atacante, o en otro sitio que permita generar contenido.
Enviar un enlace en un correo electrónico, tweet u otro mensaje.
La necesidad de un mecanismo de entrega externo para el ataque significa que el impacto del Reflected XSS es generalmente menos severo que el del Stored XSS.
Reflected XSS en contexto HTML sin nada codificado
El siguiente sitio posee un Reflected XSS en la función de búsqueda.
Al ingresar datos en el parámetro de búsqueda, estos son reflejados en el body de la respuesta del sitio:
Site
Al enviar datos, estos son enviados mediante un método GET:
Envío de datos
Como se ve a continuación, estos datos son reflejados en el body de la respuesta:
Datos reflejados
Datos reflejados
Ahora, validamos si podemos enviar código JavaScript. Se enviará el payload <script>alert(1)</script> encodeado en URL:
Payload codificado
Vemos que el payload no es codificado en la respuesta:
El payload no se codifica en la respuesta
Por lo tanto, si lo revisamos en la web, vemos que salta el pop-up con el mensaje que dejamos en el alert() enviado:
Resultado de la función alert()
Reflected XSS en atributo con angle brackets codificado en HTML
El siguiente sitio posee un Reflected XSS en la función de búsqueda.
Al ingresar datos en el parámetro de búsqueda, estos son reflejados en el body de la respuesta del sitio:
Site
Al enviar datos, estos son enviados mediante un método GET:
Datos enviados
Como se ve a continuación, estos datos son reflejados en el body de la respuesta:
Datos reflejados
Datos reflejados
Ahora enviamos el payload <script>alert(1)</script>:
Payload 01
En la respuesta, los símbolos <> se encuentran codificados, por lo tanto, no podemos usar una nueva etiqueta HTML:
Angle Brackets codificados
Como los datos se encuentran en del atributo value del tag input, podemos enviar un payload para que trabaje dentro de este mismo tag. Para este caso, usamos el payload " onmouseover="alert(1):
Payload 02
Con las primeras comillas del payload, cerramos el atributo value, y este dejará el nuevo atributo onmouseover dentro del tag input:
Payload reflejado
Ahora, si mandamos el payload directamente en la web, y pasamos el mouse sobre la barra de búsqueda, salta el pop-up con el mensaje indicado en el payload:
Payload reflejado
Relfected XSS en un string JavaScript con angle brackets codificados en HTML
El siguiente sitio posee un Reflected XSS en la función de búsqueda.
Al ingresar datos en el parámetro de búsqueda, estos son reflejados en el body de la respuesta del sitio:
Sitio
Datos enviados
Datos reflejados
Datos reflejados
Validamos si podemos ingresar el siguiente payload '</script><script>alert(1)</script>, cerrando el tag script:
Payload 01
Los angle brackets se encuentran codificados en la respuesta:
Datos reflejados
Usamos el siguiente payload '-alert(1)-', donde, se usan - para concatenar e indicar que se tiene tomar en cuenta el valor de alert():
Payload 02
Vemos que el payload no se codifica en la respuesta:
Datos reflejados
Al ingresar este payload directamente en la barra de búsqueda, vemos que salta el pop-up con el mensaje dentro de la función alert():
XSS
Reflected XSS en contexto HTML con la mayoría de las etiquetas y atributos bloqueados
Como indica el título del lab, se presentan múltiples bloqueos de etiquetas y atributos a nivel de HTML, por este motivo, es necesario identificar cuáles podemos usar.
Usando el intruder de Burp Suite, y el Cheat Sheet de PortSwigger, podemos validar las etiquetas/atributos permitidos.
Lo primero es mandar el request de la búsqueda al Intruder:
Envío a Intruder
En este, seleccionamos donde necesitamos agregar el payload:
Payload Positions
Ahora, desde la web de PortSwigger copiamos los tags:
Cheat Sheet
Estos los agregamos a la lista de payloads:
Payloads a usar
Ya con esto, le damos clic en Start attack, y cuando termine, revisamos las respuestas que tengan mayor largo, que en este caso, es body:
Responses
Con este tag, repetimos lo anterior, pero ahora agregando los events del cheat sheet:
Payload Positions
Payloads a usar
Acá podemos filtrar por dos opciones, por el status code o por el largo:
Responses
Con esto, validamos ingresando la función alert() dentro del atributo onresize, y vemos que salta el pop-up al momento de ajustar el tamaño de la página:
XSS
Para poder enviar este payload a un usuario, podemos usar el siguiente iframe:
Reflected XSS en contexto HTML con todas las etiquetas bloqueadas excepto las personalizadas
Como se especifica en el título del lab, los tags normales de HTML no pueden ser usados en este caso, debido que, estos se encuentran filtrados, por este motivo, es que se validará con el envío de un tag personalizado.
En la barra de búsqueda, ingresamos un tag no personalizado, y vemos que tenemos un error 400, indicando que el tag no se encuentra permitido:
Status Code 400
Ahora modificamos el tag a uno custom, con atributos que nos permitan inyectar JavaScript <wolf id=x tabindex=1 onfocus=alert(1)>:
Tag personalizado
Este tag es reflejado de forma correcta en la respuesta, pero al momento de querer hacer saltar el pop-up no salta, así que para generar el alert(), se llama el id con el siguiente string (#x) al final del payload:
XSS
Reflected XSS con algunas marcas SVG permitidas
Al inyectar un payload en la opción de búsqueda, vemos que nos da un error 400 especificando que el tag ingresado no se encuentra permitido:
Sitio Web
Payload de prueba
Por este motivo, realizamos fuzzing usando la herramienta Intruder para identificar que tags se encuentran permitidos:
Payload positions
Como payloads, usamos los tags que se encuentran en el Cheat Sheet de XSS de PortSwigger:
Payload settings
Podemos observar que los tags permitidos son: <svg>, <title>, <image> y <animatetransform>:
Tags permitidos
El tag <animatetransform> es un tag que se puede usar en conjunto con <svg>, el cual, permite usar atributos que ejecutan scripts:
Validación de atributos
Atributos permitidos
Usando el payload <svg><animatetransform onbegin=alert(1)> podemos explotar el XSS:
Envío del payload
XSS
Reflected XSS en la etiqueta de enlace canónico
Al revisar el código fuente, apreciamos que se tiene un enlace canónico:
Enlace canónico
Si al enlace le agregamos algún string, este se ve reflejado en el enlace canónico:
Modificación del enlace canónico
Al agregar el payload ?'onload='alert(1), este se ve reflejado en el enlace, pero no se ejecuta la función alert():
Payload 01
Revisando la información de los research que posee PortSwigger, encontramos que tienen un post donde indican con qué payload podemos explotar los enlaces canónicos, por lo tanto, usando el payload ?'accesskey='x'onclick='alert(1), y la combinación de teclas ALT+SHIFT+X, salta el pop-up con el mensaje de la función alert():
Payload 02
XSS
La combinación de teclas en los diferentes OS son:
On Windows: ALT+SHIFT+X
On MacOS: CTRL+ALT+X
On Linux: Alt+X
Reflected XSS en una cadena de JavaScript con comillas simples y backslash escapado
Al ingresar un string en la barra de búsqueda, este se refleja en la variable searchTerms dentro del código JavaScript de la respuesta:
Sitio web
Datos reflejados
Si a este payload le agregamos una comilla simple ('), este carácter es escapado mediante un backslash (\):
Carácter escapado
Por este motivo, cerramos la etiqueta script para insertar una nueva con la función alert():
Payload
XSS
Reflected XSS en una cadena de JavaScript con paréntesis angulares y comillas dobles codificado en HTML y comillas simples escapadas
Validamos como el sitio procesa los caracteres enviados en la barra de búsqueda enviando el siguiente string a'b"c/d\e:f;g-h:
Web Site
Caracteres escapados
Como se puede apreciar, las ' son escapadas, mientras que, las " son codificadas usando HTML. Por este motivo, se manda un \ para escapar el símbolo de escape, y así poder usar la comilla simple, además, se mandan dos / para generar un comentario al final de nuestro string de JavaScript. El payload enviado es \-alert(1)//:
Payload
XSS
Reflected XSS en un template literal con escape Unicode en angle brackets, comillas simples, dobles, backslash y backticks
Se ingresan los siguientes caracteres 0`a'b"c/d\e:f;g-h{i}j$k<1>2 para validar como son procesados:
Web Site
Caracteres escapados
Como no escapa los caracteres $ y {}, podemos usar templates literales enviando el siguiente payload ${alert(1)}: