Recuerdo amanecer el sábado por la mañana con un mensaje de un cliente que me comentaba una nota de prensa sobre esta vulnerabilidad, el día de antes ya había tenido algunos acercamientos con este CVE que se empezaba a caldear por RRSS, sobre todo en Twitter. De las primeras noticias que todos nos hacíamos eco por aquel entonces era la publicada en el portal de Bleeping Computer, aunque la gente de Tenable me parece que también tenían ya algo de información, que luego han ido actualizado. En todo caso, todo partía de informaciones (en aquel entonces sin muchas precisiones) que indicaban que Fortinet había comunicado a sus clientes esta vulnerabilidad crítica (CVSSv3 de 9.6) que afectaba a sus productos, inicialmente reconocido como FortiOS en versiones que iban desde la 7.0.0 hasta la 7.0.6 y 7.2.0 hasta la 7.2.1 y también FortiProxy en versiones que iban desde la 7.0.0 hasta la 7.0.6, además de la versión 7.2.0 suelta. Posteriormente se amplió el comunicado de la afectación al producto FortiSwitchManager en sus versiones 7.0.0 y 7.2.0.

Pero bien, como analistas de seguridad, después de llevarnos las manos a nuestras cabezas respectivas, nos surge la siguiente interrogante:

¿De qué va todo esto?

Bien, para decirlo rápidamente y sin andarme por las ramas se podría explicar como que se trata de una «Evasión de la autenticación en la interfaz de administración» o lo que es lo mismo y cito la definición exacta que le dio el fabricante: «Authentication bypass on administrative interface«, y que posteriormente pudimos asimilar de mejor manera gracias al fantástico trabajo que realizaron los expertos de Horizon3.ai, que se volcaron efusivamente en el análisis de esta vulnerabilidad, la identificación de indicadores de compromiso (IOC), investigación de vectores de explotación (lo que yo suelo referirme como «re-researching«), desarrollo de PoC y encomiable labor de documentación técnica para que el resto de mortales de la comunidad lleguemos a interiorizarnos con esta brecha. Tengo que decir que también caldearon las redes muy a su estilo y con olfato comercial (muy oportuno claro está).
Y bueno, para complementar la respuesta a la pregunta planteada, podemos decir que esta vulnerabilidad se trata de una inconsistencia en la validación de cabeceras HTTP (si, efectivamente como lo estás pensando, algo muy en la línea de lo que ya sucedió en F5 y VMware relativamente reciente), y que propicia por tanto que un potencial atacante envíe una petición especialmente diseñada que permite pasar por alto la autenticación que se ofrece desde el panel de administración este tipo de productos. Algo como esto básicamente:

Bien, a través del análisis en profundidad que ha realizado la gente de Horizon3.ai, hemos conocido que mediante el envío de la cabecera User-Agent con valor Report Runner, más la definición de la cabecera Fowarded con la siguiente cadena: for=[127.0.0.1]:8000;by=[127.0.0.1]:9000; es posible omitir la autenticación en determinados endpoint de la API REST del producto. A continuación un par de peticiones para ver la comparativa:

Nótese, si no lo he mencionado anteriormente, que realizando mis propias validaciones, he visto que no es necesariamente imprescindible realizar un petición PUT al objetivo, aquí para no ser demasiado «intrusivo» me decante por formar y enviar peticiones sencillamente GET.

Continúo entonces… Es evidente que la posibilidad de realizar peticiones no autenticadas a esos endpoint de la API REST será extremadamente atractivo para un atacante (y para nosotros, para que nos vamos a engañar). Aquí algunos endpoint que yo he podido localizar y que nos ofrecen diversa información del producto afectado, sin necesidad de pasar por la autenticación diseñada:

Obviamente esto lo realice «fuzzeando a ciegas» durante unos minutos. Gran ventaja nos daría revisar la documentación primero.

Dicho esto, os emplazo a visitar el blog de Horizon3.ai, que la currada que se han marcado no tiene desperdicio por ningún nado. El enlace os lo dejo al final, junto a las referencias.

Automatismos y pruebas de conceptos (PoC)

Por un lado tenemos la PoC publicada por los mismos de Horizon3.ai (CVE-2022-40684.py), que se trata de un script en python que automatiza la explotación de la vulnerabilidad mediante la actualización de la clave SSH del usuario administrador del producto. No está demás aclarar que con la ejecución exitosa de este script realizaremos un cambio evidente sobre el objetivo y probablemente podríamos alertar al blue team de nuestra intrusión. Esta PoC fue anunciada de forma temprana a través del siguiente tweet:

Otro de los automatismos que vi en su momento (muy al inicio) fue el desarrollado por el usuario Nagli (CVE-2022-40684.yaml) que se trata de una plantilla para Nuclei que es «algo menos» intrusiva ya que no altera las claves SSH de los administradores del producto, sino que mediante la inserción fake de una clave SSH permite obtener un mensaje de error del objetivo, lo cual es indicativo de que el activo es vulnerable. Les invito a darle un vistazo desde luego.

Y por último, aprovecho y dejo por aquí mis automatismos en forma de «checkers» o validadores de la vulnerabilidad. En este caso os presento 2 primeras plantillas YAML para Nuclei y un script en Python:

Template: fortinet_version.yaml

Independientemente de la vulnerabilidad, esta plantilla permite que Nuclei sea capaz de identificar las versiones de los productos de Fortinet.
Esto lo hace simplemente enviando una petición TRACE al objetivo y leyendo el json que en algunos casos devuelve el producto cuando nos enseña un «enriquecido» código de estado HTTP 405 (Method Not Allowed).
Obtenlo desde aquí: fortinet_version.yaml

Template: vuln_checker.yaml

Lo que adelantaba anteriormente, me pareció que sería interesante identificar la vulnerabilidad sin la necesidad de pasar por explotar de forma activa la misma, por tanto y validando los accesos a los distintos endpoint de la API REST se me ocurrió generar una sencilla petición GET especialmente diseñada con las cabeceras necesarias para demostrar que la vulnerabilidad está o no presente en un determinado objetivo. Para ello tomo como match el código de estado HTTP 200, busco una cadena que sé que estará presente de cumplirse lo anterior y finalmente extraigo, ya que estoy, la versión del producto.
Si quieres jugar con esta template desde aquí: vuln_checker.yaml

Script: UserEnum.py

Ya lo último que se me ocurrió preparar para cuando necesites aprovechar esta vulnerabilidad es un script llamado simplemente UserEnum.py y que permite recopilar los usuarios dados de alta en el producto vulnerable y sus respectivos perfiles, obviamente esto puede ser información que empleemos en ataques posteriores.
¿De donde obtengo estos datos? Pues simplemente de la API REST, concretamente del mismo endpoint que ya venía consultando: «/api/v2/cmdb/system/admin».

Y listo, esto era prácticamente lo que quería comentar en estas líneas, esta vulnerabilidad ha estado revolucionando las RRSS por unos días y ha generado actividad en los equipos azules y en los de respuesta y contención, por ahora ya son muchos los sistemas que se ven parcheados (curiosamente muchos «downgradeados» para evitar estar con una versión explotable) y los titulares de la prensa especializada del sector ahora están centrándose en otros nombres propios, espero traeros nuevos análisis pronto, hasta entonces!

Referencias