Einführung
In diesem Lab lernen Sie die XML External Entity (XXE) Injection kennen – eine Sicherheitslücke in Webanwendungen, die es einem Angreifer ermöglicht, die Verarbeitung von XML-Daten durch eine Anwendung zu manipulieren.
Bei XXE dreht sich im Grunde alles um das Verhalten des Parsers. Die Anwendung geht davon aus, dass sie lediglich Daten verarbeitet, doch der XML-Parser verarbeitet zusätzlich Anweisungen, die in diesem Datenformat eingebettet sind.
Wenn eine Webanwendung XML-Eingaben parst, ohne die Auflösung externer Entitäten ordnungsgemäß zu deaktivieren, können Angreifer benutzerdefinierte Entitäten definieren, die auf lokale Dateien auf dem Server verweisen. Durch das Einschleusen dieser bösartigen Entitäten in das XML-Payload kann der Angreifer den Server zwingen, sensible Dateien (wie /etc/passwd) zu lesen und deren Inhalt in der HTTP-Antwort zurückzugeben. Sie schlüpfen in die Rolle eines Sicherheitstesters, um einen XML-Endpunkt zu identifizieren, ein bösartiges Payload zu erstellen und erfolgreich Systemdateien zu extrahieren.
Identifizierung der XML-Datenverarbeitung
In diesem Schritt interagieren wir mit einer lokalen Webanwendung, die für dieses Lab bereitgestellt wurde. Die Anwendung läuft auf 127.0.0.1 unter Port 5000 und verfügt über einen Endpunkt /process, der XML-Daten akzeptiert.
XML (eXtensible Markup Language) ist ein weit verbreitetes Format zur Strukturierung und Übertragung von Daten zwischen Client und Server. Bevor wir eine XXE-Schwachstelle ausnutzen können, müssen wir zunächst bestätigen, dass die Anwendung tatsächlich XML-Eingaben verarbeitet und die geparsten Daten an uns zurückspiegelt.
Diese erste Bestätigung ist wichtig, da XXE nur möglich ist, wenn tatsächlich eine XML-Verarbeitung stattfindet. Viele Endpunkte akzeptieren Text, aber nicht alle behandeln den Body als XML.
Wir verwenden das Befehlszeilentool curl, um eine HTTP-POST-Anfrage an den Server zu senden. Eine POST-Anfrage sendet Daten an die Anwendung, und der Header Content-Type: application/xml weist den Server an, diese Daten als XML anstatt als reinen Text oder JSON zu interpretieren.
Führen Sie den folgenden Befehl in Ihrem Terminal aus, um ein einfaches XML-Payload zu senden:
curl -X POST -H "Content-Type: application/xml" -d '<root><name>LabEx User</name></root>' http://127.0.0.1:5000/process
Sie sollten eine Ausgabe sehen, die in etwa so aussieht:
Hello, LabEx User!
Diese Ausgabe bestätigt zwei wichtige Dinge. Erstens hat die Anwendung unsere XML-Daten erfolgreich geparst. Zweitens hat die Anwendung den Text innerhalb des <name>-Tags extrahiert und in der Antwort an uns zurückgegeben. Diese Rückspiegelung ist entscheidend, da sie uns später ermöglicht, die Ergebnisse unserer eingeschleusten Entitäten zu sehen.
Abfangen der XML-Anfrage
Bei realen Penetrationstests verwenden Sicherheitsforscher häufig Proxy-Tools wie Burp Suite, um Webanfragen abzufangen und zu modifizieren. Da wir ausschließlich im Terminal arbeiten, simulieren wir diesen Prozess, indem wir unser XML-Payload in einer lokalen Datei speichern. Dies macht es wesentlich einfacher, komplexe, mehrzeilige XML-Strukturen zu bearbeiten und einzuschleusen, ohne sich mit kompliziertem Escaping in der Befehlszeile herumschlagen zu müssen.
Das Verschieben des Payloads in eine Datei dient nicht nur der Bequemlichkeit. Es macht komplexe strukturierte Eingaben leichter nachvollziehbar und bearbeitbar, was wichtig ist, wenn die Syntax selbst die Ausnutzung beeinflusst.
Erstellen wir eine Datei namens payload.xml in unserem aktuellen Verzeichnis (~/project). Wir verwenden den Texteditor nano, um diese Datei zu erstellen und zu bearbeiten. Falls Sie nano noch nicht verwendet haben: Es ist ein einfacher, terminalbasierter Texteditor, der sich gut für kleine Dateien wie dieses Payload eignet.
Öffnen Sie den Editor mit:
nano payload.xml
Geben Sie die folgende Standard-XML-Struktur ein oder fügen Sie sie in die Datei ein:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<name>Security Tester</name>
</root>
Speichern Sie die Datei und beenden Sie den Editor (in nano drücken Sie Ctrl+O, dann Enter zum Speichern und Ctrl+X zum Beenden).
Senden wir diese Datei nun mit curl an den Server. Das @-Symbol weist curl an, die Daten aus der angegebenen Datei zu lesen, anstatt den String wörtlich zu nehmen.
Führen Sie den folgenden Befehl aus:
curl -X POST -H "Content-Type: application/xml" -d @payload.xml http://127.0.0.1:5000/process
Sie sollten die folgende Ausgabe sehen:
Hello, Security Tester!
Durch das Auslagern unseres Payloads in eine Datei haben wir eine saubere Arbeitsumgebung geschaffen, um in den nächsten Schritten mit der Erstellung unserer XXE-Injection zu beginnen.
Definieren einer externen Entität (DOCTYPE)
Nachdem wir nun eine funktionierende XML-Datei haben, können wir mit der Manipulation ihrer Struktur beginnen. XML erlaubt es Entwicklern, benutzerdefinierte Variablen, sogenannte "Entitäten", innerhalb einer Document Type Definition (DOCTYPE) zu definieren. Ein DOCTYPE ist ein zusätzlicher Abschnitt am Anfang eines XML-Dokuments, der Regeln oder wiederverwendbare Werte für den Parser beschreibt.
Eine Entität fungiert wie eine Abkürzung. Wenn Sie eine Entität namens test mit dem Wert Injected Data definieren, wird der XML-Parser jedes Mal, wenn Sie &test; in Ihrem XML-Dokument schreiben, dies durch Injected Data ersetzen. Wenn der Parser anfällig ist, verarbeitet er diese benutzerdefinierten Entitäten ohne Sicherheitsüberprüfungen.
Dieses harmlose Beispiel ist wichtig, da es beweist, dass die Entitätserweiterung aktiviert ist, bevor Sie zu dateibasierten externen Entitäten übergehen.
Lassen Sie uns unsere payload.xml-Datei so anpassen, dass sie eine DOCTYPE-Deklaration und eine benutzerdefinierte Entität enthält.
Öffnen Sie die Datei erneut:
nano payload.xml
Aktualisieren Sie den Inhalt der Datei so, dass er dem folgenden Code entspricht:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY test "Injected Entity Data">
]>
<root>
<name>&test;</name>
</root>
Speichern Sie die Datei und beenden Sie nano (Ctrl+O, Enter, Ctrl+X).
In diesem Payload haben wir eine Entität namens test definiert. Innerhalb des <name>-Tags haben wir diese Entität mit &test; referenziert. Senden wir dieses aktualisierte Payload an den Server, um zu sehen, ob unsere benutzerdefinierte Entität aufgelöst wird.
Führen Sie den curl-Befehl erneut aus:
curl -X POST -H "Content-Type: application/xml" -d @payload.xml http://127.0.0.1:5000/process
Sie sollten die folgende Ausgabe sehen:
Hello, Injected Entity Data!
Der Server hat &test; erfolgreich durch unseren benutzerdefinierten String ersetzt. Dies beweist, dass der XML-Parser aktiv Entitäten auflöst, was bedeutet, dass er höchstwahrscheinlich anfällig für eine XML External Entity (XXE) Injection ist.
Extrahieren lokaler Dateien (/etc/passwd)
Im vorherigen Schritt haben wir eine interne Entität definiert. Die wahre Gefahr von XXE entsteht, wenn wir eine externe Entität definieren. Durch die Verwendung des Schlüsselworts SYSTEM können wir den XML-Parser anweisen, den Wert der Entität aus einer externen Quelle zu beziehen, beispielsweise einer URL oder einem lokalen Dateipfad.
Wenn der XML-Parser des Webservers schlecht konfiguriert ist, liest er den Inhalt der von uns angegebenen Datei und bettet ihn in das XML-Dokument ein. Da die Anwendung das <name>-Tag an uns zurückspiegelt, können wir den Inhalt der Datei in der HTTP-Antwort sehen. Genau deshalb ist die Rückspiegelung für einen Angreifer so wertvoll: Sie verwandelt ein unsichtbares serverseitiges Lesen von Dateien in eine sichtbare Ausgabe im Browser oder Terminal.
Wir werden versuchen, /etc/passwd zu lesen, eine Standard-Linux-Datei, die Benutzerkontoinformationen enthält. Diese Datei ist für alle Benutzer auf dem System lesbar und daher ein häufiges Ziel für das Testen von Schwachstellen beim Dateizugriff.
Öffnen Sie Ihre Payload-Datei ein letztes Mal:
nano payload.xml
Ändern Sie die Entitätsdefinition so, dass das Schlüsselwort SYSTEM verwendet wird und mit dem Protokoll file:// auf die lokale Datei verweist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
<name>&xxe;</name>
</root>
Speichern Sie die Datei und beenden Sie nano (Ctrl+O, Enter, Ctrl+X).
Senden Sie nun das bösartige Payload an den Server:
curl -X POST -H "Content-Type: application/xml" -d @payload.xml http://127.0.0.1:5000/process
Wenn der Exploit erfolgreich ist, liest der Server die Datei /etc/passwd und gibt deren Inhalt in der Antwort zurück. Sie sollten einen großen Textblock sehen, der in etwa so aussieht:
Hello, root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
...
labex:x:1000:1000::/home/labex:/bin/zsh
!
Herzlichen Glückwunsch! Sie haben erfolgreich eine XML External Entity-Schwachstelle ausgenutzt, um sensible lokale Dateien vom Webserver zu extrahieren.
Zusammenfassung
In diesem Lab haben Sie gelernt, wie man XML External Entity (XXE)-Schwachstellen identifiziert und ausnutzt. Sie haben damit begonnen, zu überprüfen, ob eine Webanwendung XML-Daten verarbeitet und zurückspiegelt. Anschließend haben Sie gelernt, wie man benutzerdefinierte XML-Entitäten mithilfe einer DOCTYPE-Deklaration definiert. Schließlich haben Sie den Angriff eskaliert, indem Sie das Schlüsselwort SYSTEM verwendet haben, um eine externe Entität zu erstellen, die den XML-Parser des Servers dazu zwingt, die lokale Datei /etc/passwd zu lesen und deren Inhalt zurückzugeben.
Um XXE-Schwachstellen zu verhindern, müssen Entwickler sicherstellen, dass ihre XML-Parser so konfiguriert sind, dass die Auflösung externer Entitäten und DTDs (Document Type Definitions) vollständig deaktiviert ist.



