Play Framework: Un bug de XSS en el login "Secure" de tus aplicaciones Play
Play es un framework de aplicaciones webs de código abierto escrito es Scala v2 y Java v1 que sigue sigue un patrón de arquitectura Modelo Vista Controlador (MVC). Play Framework es un entorno de alta productividad y velocidad que cumple con las necesidades de los proceso de desarrollo ágil de software y que, además, integra componentes y APIs necesarias para el desarrollo moderno de aplicaciones webs, y que, como muchos otros, cuenta incluso con una integración de Latch en él.
Hace varios meses atrás reportamos el segundo XSS en el framework de Play - tiempo atrás ya habíamos reportado otro del que os hablé en el artículo "Play Framework: Ataque de Phishing usando un bug de XSS" , siendo este segundo un poco más crítico que el primero. En esta ocasión, el vector de ataque para conseguir explotar el bug de XSS ha sido la cookie y la forma de explotarlo consistía en modificar el valor de la misma para que sea enviada contra el backend del login y verla reflejada en la respuesta.
Figura 2: Playtch. Integración de Latch en Play Framework
Con este entorno a lo más que a priori se podría aspirar parecía ser solo un Self-XSS, lo que hacía que en un escenario resultara de poca utilidad. Sin embargo, en este artículo pretendo exponer cómo logramos pasar de explotar un “Self-XSS” a una especie de “XSS reflejado-persistente”.
PoC: De Self-XSS a XSS reflejado-persistente
Antes que nada vamos a dar un repaso a lo que sucede con el framework para que se pueda inyectar código con este bug. La característica que lo hace vulnerable a este ataque es el encadenamiento de dos factores que paso a contaros. El primero de ellos es que Play prioriza los mensajes de error y éxito transmitidos mediante la cookie PLAY_FLASH enviada en una petición, por delante de los mensajes establecidos en su propio fichero de configuración. De hecho, ésta es la solución que propone el framework de Play en las versiones parcheadas contra este bug.
El segundo factor es que cuando son impresos estos mensajes de error y éxito en la respuesta no pasan ningún tipo de validación. Para evitar el éxito de este ataque, como hemos comprobado, bastaría con realizar un proceso de encoding en la impresión del mensaje de error y de éxito y el problema quedaría resuelto - siempre y cuando se quisiese seguir transmitiendo los mensajes de error y éxito mediante esta cookie -.
Dándole unas vueltas para intentar explotar el fallo como algo más que un Self-XSS me percaté de un comportamiento de Play Framework que me hizo indagar en el proceso que se produce cuando un usuario trata de realizar login, ya que resulta que al enviar contra el login los parámetros username, password y autenticateToken, independientemente de ser dichos valores correctos o no, se puede enviar el parámetro "error" o "success". Lo que se obtiene como resultado es que Play Framework en la respuesta los configura como variables en la cookie FLASH. ¡Bingo!
Como he comentado antes, el problema en un principio estaba en que era necesario modificar a mano la cookie añadiendo la inyección Javascript, pero con este comportamiento esto queda resuelto resuelto ya que es posible modificar el valor de dicha cookie a través de un intento de login. Con esto ya resuelto solo sería cuestión de realizar una petición contra el login, enviando adicionalmente el parámetro "error" con nuestro payload XSS como valor. Hecho esto, vemos como en la respuesta el servidor pone en la cookie la inyección y se sobrepone a los mensajes de error del fichero de configuración, quedando reflejado el payload en la respuesta, tal que así.
Con este proceso de explotación se consigue que se pueda realizar un ataque de XSS nada más y nada menos que contra el proceso de login de todas las aplicaciones desarrolladas con Play Framework no parecheadas utilizando el módulo Secure.
Aún continué intentando darle una vuelta de tuerca al proceso para ver si se podía propagar el ataque XSS por todas las páginas de la aplicación y, por qué no, por todos las aplicaciones hechas con Play Framework bajo los subdominios. Para eso hice una serie de pruebas.
Haciendo persistente la inyección XSS en la cookie
Con ellas tenía como objetivo principal conseguir que después de recargar la página de login no se perdiera la inyección, o lo que es lo mismo, no perder la cookie con el valor configurado, ya que resultaba que una vez realizada la inyección, la cookie desaparecí. Este no es un comportamiento extraño en las cookies de tipo Flash, es más, dicho comportamiento lo tienen descrito en la documentación de Play Framework.
Por lo tanto, al encontrarme ante el problema de la no propagación de la cookie por el resto del sitio web, solo quedaba conformarnos con volver a configurar la cookie mediante la inyección inicial otra vez, de tal forma que incluso recargando la página el XSS volviese a estar presente en la respuesta y así sucesivamente a modo de bucle. El proceso sería
Pero claro, esta labor se nos iba a complicar un poco por la naturaleza de la cookie FLASH. Y es que en cualquier redirección donde no se imprimiera nuestra inyección en la respuesta significa inmediatamente la no propagación del ataque. Por ejemplo, tras realizar un proceso de autenticación entrando con usuario y contraseña válidos, el servidor devuelve en la respuesta un código 302 Redirect, junto con la cabecera Location dirigiéndonos a la raíz y en ese paso intermedio perderíamos nuestra preciada cookie.
Parchea tus aplicaciones con Play Framework
Como conclusión personal, ha sido una de esas explotaciones de las que te llenan como pocas y que, con cierta fortuna, se han dado varias condiciones para tener el escenario perfecto y así poder concatenar varios trucos hasta conseguir explotar un XSS más allá del Self-XSS. Al final, el impacto: de este bug de XSS es tan grande como que afecta a cualquier aplicación que use la página de login por defecto del módulo Secure de Play Framework vulnerable a ataques de XSS
El expediente del bug que se publicó cuando lo reportamos este año lo tenéis en la zona de Security de Play Framework, y las versiones afectadas en concreto son: Play 1.2.0 - 1.2.7, Play 1.3.0 - 1.3.3 y Play 1.4.0 - 1.4.1
Autor: Ricardo Martín (@ricardo090489)
Senior Security QA Pentester en ElevenPaths
Figura 1: Play Framework. Un bug de XSS en el login "Secure" de tus aplicaciones Play |
Hace varios meses atrás reportamos el segundo XSS en el framework de Play - tiempo atrás ya habíamos reportado otro del que os hablé en el artículo "Play Framework: Ataque de Phishing usando un bug de XSS" , siendo este segundo un poco más crítico que el primero. En esta ocasión, el vector de ataque para conseguir explotar el bug de XSS ha sido la cookie y la forma de explotarlo consistía en modificar el valor de la misma para que sea enviada contra el backend del login y verla reflejada en la respuesta.
Figura 2: Playtch. Integración de Latch en Play Framework
Con este entorno a lo más que a priori se podría aspirar parecía ser solo un Self-XSS, lo que hacía que en un escenario resultara de poca utilidad. Sin embargo, en este artículo pretendo exponer cómo logramos pasar de explotar un “Self-XSS” a una especie de “XSS reflejado-persistente”.
PoC: De Self-XSS a XSS reflejado-persistente
Antes que nada vamos a dar un repaso a lo que sucede con el framework para que se pueda inyectar código con este bug. La característica que lo hace vulnerable a este ataque es el encadenamiento de dos factores que paso a contaros. El primero de ellos es que Play prioriza los mensajes de error y éxito transmitidos mediante la cookie PLAY_FLASH enviada en una petición, por delante de los mensajes establecidos en su propio fichero de configuración. De hecho, ésta es la solución que propone el framework de Play en las versiones parcheadas contra este bug.
El segundo factor es que cuando son impresos estos mensajes de error y éxito en la respuesta no pasan ningún tipo de validación. Para evitar el éxito de este ataque, como hemos comprobado, bastaría con realizar un proceso de encoding en la impresión del mensaje de error y de éxito y el problema quedaría resuelto - siempre y cuando se quisiese seguir transmitiendo los mensajes de error y éxito mediante esta cookie -.
Figura 3: Workarround propuesto para evitar este bug |
Dándole unas vueltas para intentar explotar el fallo como algo más que un Self-XSS me percaté de un comportamiento de Play Framework que me hizo indagar en el proceso que se produce cuando un usuario trata de realizar login, ya que resulta que al enviar contra el login los parámetros username, password y autenticateToken, independientemente de ser dichos valores correctos o no, se puede enviar el parámetro "error" o "success". Lo que se obtiene como resultado es que Play Framework en la respuesta los configura como variables en la cookie FLASH. ¡Bingo!
Como he comentado antes, el problema en un principio estaba en que era necesario modificar a mano la cookie añadiendo la inyección Javascript, pero con este comportamiento esto queda resuelto resuelto ya que es posible modificar el valor de dicha cookie a través de un intento de login. Con esto ya resuelto solo sería cuestión de realizar una petición contra el login, enviando adicionalmente el parámetro "error" con nuestro payload XSS como valor. Hecho esto, vemos como en la respuesta el servidor pone en la cookie la inyección y se sobrepone a los mensajes de error del fichero de configuración, quedando reflejado el payload en la respuesta, tal que así.
Figura 4: Esquema del ataque para inyectar el payload XSS |
Con este proceso de explotación se consigue que se pueda realizar un ataque de XSS nada más y nada menos que contra el proceso de login de todas las aplicaciones desarrolladas con Play Framework no parecheadas utilizando el módulo Secure.
Figura 5: PoC de cómo se inyecta el payload XSS en la respuesta |
Aún continué intentando darle una vuelta de tuerca al proceso para ver si se podía propagar el ataque XSS por todas las páginas de la aplicación y, por qué no, por todos las aplicaciones hechas con Play Framework bajo los subdominios. Para eso hice una serie de pruebas.
Haciendo persistente la inyección XSS en la cookie
Con ellas tenía como objetivo principal conseguir que después de recargar la página de login no se perdiera la inyección, o lo que es lo mismo, no perder la cookie con el valor configurado, ya que resultaba que una vez realizada la inyección, la cookie desaparecí. Este no es un comportamiento extraño en las cookies de tipo Flash, es más, dicho comportamiento lo tienen descrito en la documentación de Play Framework.
Figura 6: Ambito de las cookies Flash |
Por lo tanto, al encontrarme ante el problema de la no propagación de la cookie por el resto del sitio web, solo quedaba conformarnos con volver a configurar la cookie mediante la inyección inicial otra vez, de tal forma que incluso recargando la página el XSS volviese a estar presente en la respuesta y así sucesivamente a modo de bucle. El proceso sería
Paso 1: Inyección inicial a través del parámetro que pasará a la cookie y con ello al HTML de la respuesta.
Paso 2: Play Framework borra esa cookie pero la inyección con código el payload de Javascript malicioso ya se encuentra en la página, con lo que se interpretará por el navegador. En el payload XSS, mediante una instrucción document.cookie=X_FLASH volvemos a establecer la misma cookie Flash con el código Javascript del payload XSS otra vez.
Paso 3: Al recargar la página dará como resultado nuevamente el borrado de la cookie, la inyección mediante la explotación del bug XSS y restablecimiento de la cookie maliciosa gracias al payload Javascript inyectado. Y así una vez tras otra indefinidamente.Ya habrán observado que no nos conformamos con poco, por lo que le di una vuelta de tuerca más si cabe, y para nuestra alegría comprobamos que los mensajes de error y éxito aparecían por toda la web desarrollada con Play Framework. Esto significaba que tal vez, tras ser inyectada mediante el login, se podía conseguir propagar la cookie por todas las vistas.
Pero claro, esta labor se nos iba a complicar un poco por la naturaleza de la cookie FLASH. Y es que en cualquier redirección donde no se imprimiera nuestra inyección en la respuesta significa inmediatamente la no propagación del ataque. Por ejemplo, tras realizar un proceso de autenticación entrando con usuario y contraseña válidos, el servidor devuelve en la respuesta un código 302 Redirect, junto con la cabecera Location dirigiéndonos a la raíz y en ese paso intermedio perderíamos nuestra preciada cookie.
Parchea tus aplicaciones con Play Framework
Como conclusión personal, ha sido una de esas explotaciones de las que te llenan como pocas y que, con cierta fortuna, se han dado varias condiciones para tener el escenario perfecto y así poder concatenar varios trucos hasta conseguir explotar un XSS más allá del Self-XSS. Al final, el impacto: de este bug de XSS es tan grande como que afecta a cualquier aplicación que use la página de login por defecto del módulo Secure de Play Framework vulnerable a ataques de XSS
Figura 7: Expediente de este bug de XSS en Play Framework |
El expediente del bug que se publicó cuando lo reportamos este año lo tenéis en la zona de Security de Play Framework, y las versiones afectadas en concreto son: Play 1.2.0 - 1.2.7, Play 1.3.0 - 1.3.3 y Play 1.4.0 - 1.4.1
Autor: Ricardo Martín (@ricardo090489)
Senior Security QA Pentester en ElevenPaths
Via: www.elladodelmal.com
Play Framework: Un bug de XSS en el login "Secure" de tus aplicaciones Play
Reviewed by Zion3R
on
4:04
Rating: