miércoles, 9 de diciembre de 2015

Robando credenciales de Sony mediante redirección abierta

Las vulnerabilidades de redirección abierta (Open redirection) suelen ser consideradas de baja importancia. Sin embargo, uno de los factores que elevan la criticidad de este tipo de fallos es su presencia en procesos de registro o de autenticación, ya que el usuario parte de una predisposición para facilitar sus credenciales de acceso. En este post veremos la protección que implementaba Sony contra este tipo de ataques y cómo fue posible evadirla con un vector que puede ser muy útil en diversas situaciones, no necesariamente relacionadas con la explotación de una redirección abierta.

Este fallo fue reportado a Sony en mayo de 2015 y solucionado cuatro meses más tarde. Finalmente, fui añadido en agradecimiento a su "Hall of Thanks".

Si intentamos registrarnos en cualquiera de las webs oficiales de Sony (www.sony.es, www.sony.de, www.sony.fr, etc.) veremos que, tras pulsar el botón correspondiente para crear una cuenta, somos redirigidos a una URL de este tipo:

https://www.sony.es/mysony/register?email=email%40dominio.com&check=true&returnUri=%2Fmysony

Examinando el código HTML de la página se puede apreciar cómo el valor del parámetro "returnUri" se refleja en un campo oculto del formulario:

Figura 1. Campo oculto "returnUri" en formulario de registro
Tras completar toda la información requerida y enviarla, recibimos en nuestro email el típico correo electrónico para confirmar el registro con un enlace parametrizado que incluye un token aleatorio y la ruta facilitada en el parámetro "returnUri". Finalmente, tras pulsar en este enlace somos redirigidos a la página que nos confirma la activación de la cuenta:

Figura 2. Página de confirmación de activación de la cuenta y código HTML

En la imagen anterior podemos apreciar dos cosas interesantes. La primera es que Sony invita a iniciar sesión con la cuenta recién creada, por lo que el usuario estará predispuesto a introducir sus credenciales de acceso en el siguiente paso. La segunda es que el botón "Continuar" contiene un enlace a la dirección que se introdujo inicialmente en el parámetro "returnUri". Por tanto, si este parámetro aceptara cualquier URL sería un escenario ideal para un ataque de redirección abierta con el cual enviar un enlace de registro manipulado y conseguir que una víctima introdujera sus credenciales en un dominio controlado por el atacante.

El primer intento básico fue introducir en el parámetro "returnUri" distintas URL del tipo http://dominio.atacante.com, https://..., HtTp://..., HttPs://..., data:, javascript:, etc. Sin embargo, cualquier valor que no empezara por un caracter "/" (%2F codificado en URL) hacía que el parámetro oculto del formulario HTML de la "Figura 1" fuera eliminado automáticamente, asignándose posteriormente el valor por defecto %2F en el enlace recibido en el email de confirmación.

El segundo intento, como algunos estaréis pensando, fue probar con una doble barra una URL del tipo //dominio.atacante.com, ya que esto sería equivalente a https://dominio.atacante.com. El resultado era el mismo que en el caso anterior.

Llegados a este punto, ¿existe alguna manera de reflejar una URL absoluta en el código HTML comenzando con un y solo un caracter "/" (%2F)? Sorprendentemente, se puede conseguir esto utilizando cadenas del tipo:

 %2F%09%2Fdominio.atacante.com

Los caracteres %09, %10 y %13 (tabulador, nueva línea y retorno de carro respectivamente) pueden ser introducidos en medio de los dos caracteres "/" y el resultado es equivalente a //dominio.atacante.com y, por tanto en este caso, a https://dominio.atacante.com. Utilizando este método el ataque no era detectado por Sony y el parámetro "returnUri" no era eliminado del formulario, con lo que nuestra redirección abierta funcionó perfectamente:


Este vector suele resultar muy efectivo en cualquier contexto web en el que deseamos romper la "jaula" que nos impone un path relativo. Si por otro lado estás en el bando defensivo como programador, conviene recordar que para evitar el uso de URL externas no será suficiente comprobar que la cadena introducida por el usuario comience por una sola barra, ya que habrá que tener en cuenta la posible presencia de los caracteres de separación mencionados anteriormente.

¡Un saludo! 

viernes, 1 de mayo de 2015

Hackeando eBay (Validación javascript + XSS + CSRF)

Como todos los sistemas que basan su actividad principal en el movimiento de dinero entre sus clientes, eBay es un lugar muy atractivo para un ciberdelincuente. Un XSS persistente como el que se va a detallar en este post es todo lo que se necesitaría para poder comprometer las acciones y la información de otros usuarios, y sacar provecho material con ello. A pesar de esto, eBay es ya famoso por tomarse con calma los reportes de seguridad y a su equipo le llevó unos ocho meses arreglar el problema desde su comunicación en agosto de 2013. En abril de 2014, después de solucionarse, fui finalmente añadido a su página de agradecimientos "Responsible Disclosure Acknowledgements".

El fallo de seguridad se debe a la concatenación de tres errores en serie. En mi opinión, es un buen ejemplo de cómo algunos problemas pueden no ser demasiado peligrosos ni complicados de explotar de forma aislada, pero juntos pueden dar un buen dolor de cabeza.

Validación javascript

En busca de algún fallo XSS, lo primero que intenté fue introducir algunos caracteres como ", <, >, ', etc. en la creación de nuevas carpetas del sistema de mensajes privados de eBay. Al hacer esto, se mostraba el error "Escribe un nombre de carpeta válido". Sin embargo, llamaba la atención que al enviar uno de estos caracteres problemáticos no se reflejaba ninguna petición web en el historial del navegador, lo que indicaba que la validación se estaba produciendo en el lado del cliente por medio de javascript. Aunque tengamos constancia de que se está produciendo una validación javascript que podríamos saltarnos fácilmente, esto no quiere decir que no haya una segunda validación en el servidor que nos pare los pies.

(¿Self?) XSS

Armado con un proxy, capturé la petición que enviaba mi navegador tras especificar un nombre de carpeta válido, y modifiqué el valor del parámetro por algo “inválido” más interesante como <script>alert(/XSS/)</script>. Ante mi sorpresa, al refrescar la bandeja de entrada apareció la alerta javascript, lo que confirmaba que no se producía ninguna validación del parámetro en el servidor:

XSS en nombres de carpetas
Ok, tenemos un fallo XSS, pero de momento es un triste Self-XSS que solo podemos explotar en nuestra propia cuenta. Para que esto fuera realmente peligroso, necesitaríamos poder crear carpetas de mensajes en las cuentas de otros usuarios sin su permiso y colarles nuestro código javascript en los nombres de carpeta. Uff, ¿estaba pidiendo mucho? Merecía la pena comprobarlo...

Self-XSS + CSRF = Owned!!

Una posibilidad para poder crear carpetas en cuentas ajenas, es que existiera un fallo de tipo CSRF. Si analizábamos la petición, nos fijamos en que existían dos candidatos a aguarnos la fiesta como tokens anti-CSRF: stok y pId:


Petición de creación de carpeta
Sin embargo, para mi segunda sorpresa, cualquier valor de estas variables era válido en una petición exitosa.

Debido a los tres fallos (validación de parámetros en cliente, self-XSS y CSRF), finalmente podemos construir una página maliciosa que fuerce la creación de una carpeta en la cuenta de otro usuario, y ejecutar código javascript arbitrario en su navegador:


eBay solucionó el problema de XSS mostrando las entidades html correspondientes para los caracteres especiales, e incluyendo un nuevo parámetro "srt" como token anti-CSRF dentro de la cadena JSON codificada del parámetro "request".

¡Un saludo!

jueves, 8 de enero de 2015

Salvando obstáculos en ataques XXE: explotación en atributos, ficheros mal formados y técnicas OOB

Aunque los ataques XXE (XML External Entity) son bastante conocidos, hay ciertas limitaciones que se nos suelen presentar a la hora de explotarlos, y cuyas técnicas para salir airoso, a día de hoy no están tan extendidas. Por esta razón, me ha parecido interesante escribir un post sobre algunas de estas limitaciones y cómo superarlas.

Un fallo de seguridad XXE es uno de esos fallos que te hacen saltar de la silla cuando te encuentras con él. No es para menos, ya que permite maldades tales como acceso al sistema de ficheros, escaneo de la Intranet, denegaciones de servicio o, incluso, ejecución remota de código. Para entender básicamente cómo funciona, antes de seguir leyendo puedes hacer click en este post de nuestros amigos de Security by default.

Para que después de saltar de la silla no te acabes dando con la lámpara en la cabeza, aquí te presentamos un resumen de los problemas más comunes y cómo abordarlos. En los ejemplos, el objetivo del atacante será leer el fichero /etc/passwd del servidor.

[ Explotación en atributos ]


Si intentamos explotar un XXE de la forma habitual dentro de un atributo XML, veremos que el ataque no tendrá éxito, ya que las entidades no son procesadas directamente en este contexto.

- Lo que NO funciona:


- Lo que funciona:


Donde el contenido del fichero evil.xml es el siguiente:


Por suerte, los parámetros XML acuden al rescate. Estos parámetros cumplen la misma función que las entidades, pero se usan en la definición del documento (DTD). En el ejemplo anterior, definimos la entidad "xxe" de manera indirecta haciendo uso de un parámetro que se resuelve hacia una URL externa controlada por nosotros en nuestro "evilserver", y que a su vez hace uso de parámetros que resuelven el contenido del fichero que queremos leer del servidor.

[ Ficheros mal formados ]


Otro problema habitual es que una vez que se expande una entidad XML con el contenido de un fichero que contiene caracteres como <, >, ", etc., el XML original puede acabar mal formado, por lo que el parser no podrá completar su proceso y nuestro ataque no funcionará. Una solución es intentar que el contenido del fichero quede dentro de un bloque <![CDATA[...]]>. Sin embargo, no podemos incluir este bloque directamente, ni siquiera con entidades definidas en el XML.

- Lo que NO funciona:



- Lo que funciona:


Donde el contenido del fichero join.dtd es el siguiente:


Como vemos, finalmente logramos construir nuestro bloque CDATA haciendo uso, de nuevo, de parámetros XML, y apoyándonos en una web externa controlada por nosotros que compone las partes definidas en el XML original. Aunque esta técnica funcionará en la mayoría de los casos, puede que falle si el fichero que queremos leer del servidor contiene los caracteres & o % o si intentamos leer ficheros binarios.

[ Técnicas OOB (Out of Band) ]


En ocasiones, aunque tenemos indicios de que la aplicación es vulnerable a ataques XXE, ningún dato del XML que enviamos es finalmente devuelto al usuario tras el parseo. Al igual que ocurre con la explotación de otro tipo de vulnerabilidades como SQL inyection, también existen técnicas OOB para hacer que el servidor víctima envíe el contenido hacia un servidor controlado por el atacante:


Donde el contenido del fichero send.dtd es el siguiente:


Como en esta ocasión construimos una URL externa dinámicamente con el contenido del fichero extraído, es posible que tengamos problemas si el parser es delicado y no acepta todos los caracteres del contenido que se van a incluir automáticamente en la URL. Pero incluso en esta situación nos quedan algunas cartas bajo la manga por jugar. Haciendo uso del protocolo FTP y de un servidor falso, probablemente podamos acabar leyendo el fichero siguiendo los estupendos ejemplos que detalla Ivan Novikov en este enlace.

Aparte de las técnicas anteriores, existe un abanico de posibilidades de explotación bastante interesante dependiendo de los protocolos disponibles en el servidor. gopher://, jar://,  php:// o expect:// por ejemplo, nos abrirían las puertas para poder leer ficheros binarios sin restricción de caracteres, incluso poder directamente subir ficheros al servidor o ejecutar código arbitrario.
Para más  información sobre estas y otras técnicas, podéis consultar las fuentes de documentación que os dejo al final del post.

¡Un saludo!

Fuentes:
Black Hat EU 2013 - XML Out-of-Band Data Retrieval by Alexey Osipov & Timur Yunusov
AppSec USA 2013 - What You Didn't Know About XML External Entities Attacks by Timothy Morgan
XML Schema, DTD, and Entity Attacks by Timothy Morgan & Omar Al Ibrahim
XXE OOB exploitation at Java 1.7+