Image
Cómo descubrí la vulnerabilidad Server-Side Request Forgery (SSRF)

Cómo descubrí la vulnerabilidad Server-Side Request Forgery (SSRF)

¡Hola!

En el post de hoy vamos a hablar sobre un nuevo CVE descubierto en el software NavigateCMS, un CMS de código abierto que permite la gestión de páginas web. La vulnerabilidad descubierta se denomina Server-Side Request Forgery (SSRF), la cual hasta el año pasado no formaba parte del Top 10 de OWASP, con su reciente aparición en la actualización de 2021:

Esta vulnerabilidad, junto con su antecesor Security Logging and Monitoring, han sido elegidos en la encuesta realizada por OWASP a múltiples profesionales de la ciberseguridad para incluirlas como vulnerabilidades más relevantes. 

¿Qué es un SSRF?

Una aplicación web vulnerable a SSRF permitiría a un atacante la posibilidad de acceder a recursos a través del servidor web, siendo este el que realizaría la petición a los recursos en cuestión. La flexibilidad de una URL es lo que hace que un SSRF sea de carácter crítico, ya que permite acceder a una amplia variedad de servicios, no solo a HTTP/S.

En el ejemplo mostrado, el parámetro content es vulnerable a SSRF si al enviar una URL apuntando a un recurso interno de la red, el servidor realiza la petición a dicho recurso y devuelve la respuesta al atacante, siendo capaz no solo de acceder, sino de interactuar con el servicio en cuestión.

Impacto y riesgos

El impacto puede variar según las relaciones de confianza que existan en la red donde se encuentra el servidor vulnerable. El caso más crítico sería el acceso a servicios dentro de la red interna, y la posibilidad de movimiento lateral por la red, poniendo en peligro la confidencialidad, integridad y accesibilidad de los datos de los usuarios.

Los siguientes riesgos pueden darse en caso de que un servidor sea vulnerable a SSRF:

  • Exposición de datos sensibles: debido a la flexibilidad de una URL, sería posible el acceso a servicios que contengan información sensible como pueden ser bases de datos o ficheros internos del servidor vulnerable. En entornos cloud, las credenciales provisionales a una instancia Amazon EC2 se almacenan en una ruta fija:

    http://169.254.169.254/latest/meta-data/iam/security-credentials/{role-name}

Dependiendo del rol IAM que se pudiera comprometer, sería posible desde obtener datos sensibles de los usuarios, hasta ejecución remota de comandos en la instancia EC2.

  • Reconocimiento de la red interna: muchos servicios devuelven metadata o tardan cierto tiempo en responder cuando se les hace una petición. Este tipo de comportamiento puede usarse para hacer reconocimiento de servicios en la red interna, y por tanto expandir la ventana de ataque.
  • Denegación de servicio (DoS): dado que un servidor vulnerable a SSRF permite a un atacante acceder a otros servicios, este podría enviar suficiente cantidad de peticiones para que el servicio objetivo no pueda con tanta carga, y por tanto deniegue el acceso a usuarios legítimos.
  • Ejecución Remota de Comandos (RCE): ciertos servicios permiten la ejecución de comandos mediante el uso de peticiones específicas, como es el caso de Redis. Un atacante podría usar este comportamiento para alcanzar otros objetivos y moverse lateralmente por la red. 

CVE-2022-28117 - SSRF en NavigateCMS

Ahora que se tiene el contexto de la vulnerabilidad, y el alcance de esta, vamos a desarrollar el CVE encontrado en NavigateCMS.

La vulnerabilidad reside en el parámetro URL de una petición que se envía nada más iniciar sesión en el panel de administración:

Petición legítima

Para confirmar que el servidor está realizando una petición a la URL indicada, es posible levantar nuestro propio servidor HTTP sustituyendo el valor actual por el siguiente: http://<IP>/ssrf_test, donde <IP> corresponde al servidor HTTP bajo nuestro control, este recibe la petición del servidor vulnerable:

Petición modificada explotando SSRF

Petición recibida por parte del servidor vulnerable

Durante las pruebas, se observó que parte del contenido de la respuesta obtenida se mostraba en el debug de PHP, como argumento de la función SimpleXMLElement() de la clase lib/packages/feeds/feed_parser.class.php , lo que confirma que de alguna manera la aplicación habría recuperado el contenido de la petición realizada.

Analizando la clase mencionada en el debug de PHP, se comprueba que la función está cargando el contenido de la variable $rawFeed, la cual se define en la línea 65 como el valor del atributo data de la propia clase:

feed_parser.class: SimpleXmlElement function

La clase define este atributo en la función load():

Esta función recibe como argumento una variable $url, que resulta ser el valor del parámetro URL controlado por el usuario.

En la línea 25, la función genera un fichero feed cuyo nombre corresponde al valor obtenido de aplicar la función hash MD5 sobre la variable $url, o lo que es lo mismo, la URL proporcionada por parámetro. La variable global NAVIGATE_PRIVATE hace referencia al directorio private de la ruta raíz por defecto. Este valor se puede obtener del fichero cfg/globals.php

y el valor de la variable $website->id es 1 por defecto. Por lo tanto, para la URL enviada, este sería su correspondiente fichero:

private/1/cache/ 89a7164a5ad8a7f58f1cae13a65cb441.feed

La creación de este fichero es esencial para la explotación del SSRF, ya que en la línea 39, la aplicación obtiene la respuesta de la URL proporcionada y la almacena en dicho fichero. De esta forma, es posible acceder al contenido de la petición realizada a nuestro servidor HTTP:

Accediendo al contenido de la petición realizada por el servidor vulnerable

Del mismo modo que se ha usado el servidor vulnerable para realizar peticiones a otros servicios, sería posible acceder a ficheros internos con el schema file://. Supongamos que se quiere obtener el fichero /etc/passwd, la URL que se debería enviar al servidor sería file:///etc/passwd

Solicitando el fichero passwd del servidor vulnerable

Y proporcionando la ruta adecuada como se ha explicado anteriormente, es posible acceder al contenido del mismo.

Recuperando el contenido del fichero passwd

Es proveedor fue notificado y añadió los parches necesarios para mitigar la vulnerabilidad:

https://www.navigatecms.com/en/blog/development/navigate_cms_update_2_9_5

Protección contra SSRF

Es realmente complicado evitar un SSRF, ya que en multitud de ocasiones es necesaria la comunicación entre diferentes servicios usando URLs. Teniendo esto en cuenta, las recomendaciones más acertadas serían las siguientes:

  • Fijar la URL a la que se quiere acceder: de forma que un usuario no tenga manera de modificar dicha URL por otra con fines maliciosos.
  • Lista blanca de URLs: proveer a la aplicación con una lista blanca puede reducir considerablemente la aparición de SSRF. Sin embargo, hay que tener en cuenta que las URLs son un estándar muy flexible con multitud de sintaxis aceptadas, que podrían ser abusadas para saltar este tipo de protecciones. 
  • Filtrado y detección de URLs maliciosas: toda URL que no cumpla con los requisitos anteriores no debe ser procesada. Por ejemplo, aquellas con schemas como file://, ftp://, smtp://, entre otros no deben ser aceptadas si la aplicación no se ha desarrollado para ello. 
  • Implementar reglas de Firewall:  para aumentar la defensa en profundidad de la red, se deben implementar reglas que eviten el tráfico no deseado entre servidores. Un ejemplo de tráfico no legítimo sería un servidor web tratando de comunicarse con el DC de una red interna. Debe haber separación de entornos para que, en caso de explotación, los atacantes no puedan moverse lateralmente. 

Conclusiones

Las vulnerabilidades de tipo SSRF son cada vez más frecuentes debido a la amplia demanda de entornos cloud como AWS. Es necesario tener conocimiento de estos y saber qué medidas aplicar para protegerse. ¡Esperamos que este post os haya servido de ayuda y nos vemos en el siguiente!


Roberto Cruz Ojosnegros