XML External Entity (XXE) Angriffe verhindern
AI generated
OWASP
0x00
OWASP Top 10 · A05 Security Misconfiguration
XML External Entity (XXE) Angriffe verhindern
Wie externe Entities in XML missbraucht werden und wie man sich schützt

XML-Parser mit aktivierter externer Entity-Verarbeitung lassen sich für Dateizugriff oder SSRF missbrauchen. Wir zeigen, wie XXE funktioniert, warum viele moderne XML-Bibliotheken das standardmäßig deaktiviert haben, und wie DOMDocument in PHP explizit abgesichert wird.

13 Min. Lesezeit XXE DOMDocument absichern

1. Was ist ein XXE-Angriff?

XML erlaubt die Definition eigener Entities innerhalb eines Dokuments, ähnlich wie Variablen. Externe Entities gehen einen Schritt weiter und können auf eine externe Ressource verweisen, etwa eine lokale Datei oder eine URL. Verarbeitet ein XML-Parser diese externen Entities, ohne dass der Entwickler das bewusst so konfiguriert hat, entsteht die Grundlage für einen XXE-Angriff. Die Schwachstelle ist seit vielen Jahren bekannt, taucht in Sicherheitsaudits aber immer wieder auf, weil XML-Verarbeitung oft in älteren, seltener geprüften Codeteilen steckt.

Ein Angreifer definiert dabei im XML-Dokument eine externe Entity, die auf eine sensible lokale Datei wie /etc/passwd oder eine interne Konfigurationsdatei verweist, und referenziert diese Entity anschließend an einer Stelle, deren Inhalt in der Antwort der Anwendung sichtbar wird.

2. Wie ein XXE-Angriff im Detail funktioniert

Ein typisches bösartiges XML-Dokument definiert im DOCTYPE-Bereich eine externe Entity mit dem Schlüsselwort SYSTEM, gefolgt von einem Pfad oder einer URL. Wird diese Entity anschließend in einem Textknoten referenziert, ersetzt ein anfälliger Parser die Referenz durch den Inhalt der referenzierten Ressource und baut ihn direkt in den geparsten Dokumentbaum ein.

Zusätzlich zur libxml-Konfiguration lehnt die abgesicherte Variante im folgenden Beispiel jedes Dokument mit einem DOCTYPE grundsätzlich ab, da eine Rechnungs- oder Bestell-XML fachlich niemals eine Doctype-Definition benötigt. Diese Kombination aus Konfiguration und fachlicher Validierung reduziert die Angriffsfläche auf ein Minimum, selbst falls sich das Verhalten einer libxml-Version in Zukunft ändern sollte.


<?php

declare(strict_types=1);

namespace App\Service;

final class InvoiceXmlImporter
{
    // Verwundbar: Externe Entities und Netzwerkzugriff sind nicht deaktiviert
    public function importVulnerable(string $xmlContent): \DOMDocument
    {
        $document = new \DOMDocument();
        $document->loadXML($xmlContent);

        return $document;
    }

    // Abgesichert: Externe Entities, DTDs und Netzwerkzugriff explizit sperren
    public function importSecured(string $xmlContent): \DOMDocument
    {
        $document = new \DOMDocument();

        // Seit PHP 8 sind externe Entities in libxml standardmäßig deaktiviert,
        // die explizite Konfiguration bleibt trotzdem als defense in depth sinnvoll.
        $previousSetting = libxml_use_internal_errors(true);

        $success = $document->loadXML($xmlContent, LIBXML_NONET);

        if ($success === false || $document->doctype !== null) {
            libxml_use_internal_errors($previousSetting);
            throw new \InvalidArgumentException('XML document with DOCTYPE is not allowed.');
        }

        libxml_use_internal_errors($previousSetting);

        return $document;
    }
}

3. Warum viele moderne Bibliotheken bereits schützen

Seit PHP 8.0 verarbeitet die zugrunde liegende libxml-Bibliothek externe Entities standardmäßig nicht mehr automatisch, nachdem in älteren PHP-Versionen die Funktion libxml_disable_entity_loader explizit aufgerufen werden musste. Diese Funktion ist inzwischen als deprecated markiert, weil ihr Zweck durch das neue Standardverhalten weitgehend übernommen wurde. Projekte, die noch auf PHP 7 oder älter laufen, sollten diesen Aufruf trotzdem konsequent beibehalten, da sie sonst vollständig auf den alten, unsicheren Standardzustand angewiesen sind.

Aehnliche Entwicklungen gab es in vielen anderen Sprachökosystemen: Moderne XML-Bibliotheken liefern XXE-sichere Defaults aus, weil die Schwachstelle über Jahre so häufig auftrat, dass ein Opt-in statt eines Opt-out als sinnvoller galt. Trotzdem bleibt Vorsicht geboten, weil ältere Bibliotheksversionen, Legacy-Code oder alternative XML-Parser wie SimpleXML unter bestimmten Konfigurationen weiterhin anfällig sein können.

4. Typische Einfallstore für XXE

XXE tritt überall dort auf, wo eine Anwendung XML-Daten von außen entgegennimmt und parst: Datei-Uploads im XML-, SVG- oder DOCX-Format, SOAP-Schnittstellen, RSS- und Atom-Feed-Importe sowie Konfigurationsimporte, die im XML-Format vorliegen. Besonders SVG-Dateien werden oft übersehen, obwohl sie technisch vollwertige XML-Dokumente mit DOCTYPE-Unterstützung sind. Auch Office-Formate wie DOCX oder XLSX bestehen intern aus mehreren XML-Dateien in einem ZIP-Container und sind deshalb potenziell ebenso betroffen.

Auch scheinbar interne Schnittstellen sind betroffen, etwa ein XML-basierter Import von Produktdaten oder Rechnungen aus einem ERP-System, wenn die hochgeladene Datei nicht ausschließlich von vertrauenswürdigen internen Systemen stammt, sondern etwa von externen Lieferanten hochgeladen werden kann. Gerade B2B-Schnittstellen mit vielen angebundenen Partnern sind hier besonders exponiert, da jeder einzelne Partner potenziell zum Einfallstor werden kann.

5. Folgen eines erfolgreichen XXE-Angriffs

Ein erfolgreicher XXE-Angriff erlaubt häufig das Auslesen beliebiger lokaler Dateien, auf die der PHP-Prozess Lesezugriff hat, inklusive Konfigurationsdateien mit Datenbank-Zugangsdaten oder privaten Schlüsseln. Ist zusätzlich Netzwerkzugriff durch den Parser möglich, lässt sich XXE auch für SSRF-Angriffe gegen interne Systeme nutzen, etwa um Cloud-Metadaten-Endpunkte oder interne Admin-Oberflächen anzusprechen, die von außen sonst nicht erreichbar wären.

In besonders ungünstigen Konfigurationen sind sogar sogenannte Billion-Laughs-Angriffe möglich, bei denen verschachtelte Entity-Definitionen exponentiell expandieren und den Server durch Speicher- oder CPU-Erschöpfung in einen Denial-of-Service-Zustand versetzen. Solche Angriffe benötigen nicht einmal externen Netzwerkzugriff, da die Entities vollständig innerhalb des Dokuments definiert werden können, was sie besonders schwer allein durch Netzwerkfilterung zu verhindern macht.

6. Explizite Absicherung in PHP

Auch wenn PHP 8 externe Entities standardmäßig deaktiviert, empfiehlt sich weiterhin die explizite Verwendung von LIBXML_NONET, um jeglichen Netzwerkzugriff durch den Parser zu unterbinden, sowie eine bewusste Ablehnung von Dokumenten mit DOCTYPE-Definition für alle Formate, die fachlich keine Doctype benötigen. Diese defense-in-depth-Strategie schützt auch dann, wenn eine Anwendung versehentlich auf einer älteren PHP-Version oder in einer Umgebung mit abweichender libxml-Konfiguration betrieben wird.

Für SimpleXML gelten dieselben zugrunde liegenden libxml-Einstellungen wie für DOMDocument, da beide auf derselben C-Bibliothek aufbauen. Wird XML über simplexml_load_string verarbeitet, sollten dieselben Flags wie LIBXML_NONET gesetzt und die DOCTYPE-Prüfung ebenso konsequent durchgeführt werden. Dasselbe gilt für XMLReader und die SOAP-Erweiterung, die intern ebenfalls auf libxml aufsetzen und deshalb dieselben Absicherungsprinzipien benötigen.

7. Sonderfall SVG-Uploads

SVG-Dateien werden in Upload-Formularen oft wie normale Bilddateien behandelt, sind technisch aber vollwertiges XML und können DOCTYPE-Definitionen mit externen Entities enthalten. Wird eine hochgeladene SVG-Datei serverseitig geparst, etwa für eine Vorschau oder Größenanpassung, muss dieselbe XXE-Absicherung greifen wie bei jedem anderen XML-Import.

Eine zusätzliche, robuste Maßnahme ist, hochgeladene SVG-Dateien vor der Auslieferung durch eine dedizierte Sanitizer-Bibliothek zu bereinigen, die DOCTYPE-Definitionen, Skript-Tags und externe Referenzen konsequent entfernt, statt sich ausschließlich auf die Parser-Konfiguration zu verlassen. Diese doppelte Absicherung lohnt sich besonders bei Uploads, die später direkt im Browser eines anderen Nutzers angezeigt werden, da dort zusätzlich Cross-Site-Scripting-Risiken durch eingebettete Skripte drohen.

8. Testing und Code-Review für XXE

Ein gezielter Test schickt an jeden XML-verarbeitenden Endpunkt ein Dokument mit einer externen Entity, die auf eine bekannte, harmlose lokale Datei verweist, etwa eine PHP-eigene Konfigurationsdatei, und prüft, ob deren Inhalt in der Antwort auftaucht. Zusätzlich sollte ein Dokument mit Verweis auf eine interne Test-URL genutzt werden, um SSRF über XXE auszuschließen. Ein dritter Testfall mit einer moderat verschachtelten Entity-Definition deckt ausserdem ab, ob der Parser gegen einfache Billion-Laughs-Varianten geschützt ist.

Im Code-Review lohnt sich eine gezielte Suche nach loadXML-, simplexml_load_string- und SOAP-Aufrufen, um sicherzustellen, dass jede dieser Stellen entweder auf einer aktuellen PHP-Version mit sicherem Standardverhalten läuft oder explizit mit LIBXML_NONET und einer DOCTYPE-Ablehnung abgesichert ist.

9. Best Practices und Checkliste

Jede Stelle, die XML aus einer nicht vollständig vertrauenswürdigen Quelle parst, sollte explizit LIBXML_NONET setzen, Dokumente mit DOCTYPE grundsätzlich ablehnen, sofern fachlich keine Doctype benötigt wird, und auf einer aktuellen PHP-Version mit sicherem libxml-Standardverhalten laufen.

Ergänzend gehören eine spezielle Behandlung von SVG-Uploads, ein automatisierter XXE-Test pro XML-Endpunkt sowie ein regelmäßiges Update der zugrunde liegenden libxml-Version zu einer robusten Absicherung gegen XXE.

Einfallstor Beispiel Risiko Gegenmaßnahme
XML-Datei-Upload Rechnungsimport per XML Auslesen lokaler Dateien DOCTYPE ablehnen, LIBXML_NONET
SVG-Upload Profilbild im SVG-Format XXE über Bild-Endpunkt SVG-Sanitizer plus Parser-Absicherung
SOAP-Schnittstelle Externe Partneranbindung SSRF über XML-Payload Netzwerkzugriff im Parser deaktivieren
Feed-Import RSS/Atom-Feed einlesen Denial of Service via Billion Laughs Entity-Expansion begrenzen, DOCTYPE sperren

Mironsoft

Security-Audits, OWASP-konforme Härtung und sichere Architektur

Anwendungen, die einem echten Angriffsversuch tatsächlich standhalten?

Wir prüfen bestehende Anwendungen auf klassische OWASP-Schwachstellen, unsichere Authentifizierung und fehlende Input-Validierung und bauen daraus eine Architektur, die Angriffsflächen strukturell reduziert statt nur einzelne Symptome zu flicken.

Security-Audit

OWASP Top 10, Auth-Flows und Input-Validierung systematisch auf Schwachstellen prüfen.

Sichere Architektur

Rate-Limiting, Verschlüsselung und Zugriffskontrollen von Grund auf richtig aufbauen.

Incident-Vorbereitung

Logging, Monitoring und Reaktionsprozesse für den Ernstfall etablieren.

10. Zusammenfassung

XXE

Ursache

Parser verarbeitet externe Entities in XML-Dokumenten.

Erkennung

Test mit Entity-Referenz auf bekannte lokale Datei.

Fix

LIBXML_NONET, DOCTYPE-Ablehnung, aktuelle PHP-Version.

Prävention

Code-Review auf loadXML-Aufrufe, SVG-Sanitizing.

11. FAQ: XXE

1Was ist eine externe XML-Entity?
Eine externe Entity ist eine im DOCTYPE-Bereich eines XML-Dokuments definierte Referenz auf eine externe Ressource wie eine lokale Datei oder eine URL, die der Parser beim Verarbeiten auflösen kann.
2Ist PHP seit Version 8 automatisch gegen XXE geschützt?
Die zugrunde liegende libxml-Bibliothek verarbeitet externe Entities seit PHP 8 standardmäßig nicht mehr automatisch, eine explizite Absicherung mit LIBXML_NONET und DOCTYPE-Ablehnung bleibt aber als zusätzliche Sicherheitsebene empfehlenswert.
3Was ist libxml_disable_entity_loader und wird sie noch benötigt?
Diese Funktion musste in älteren PHP-Versionen aufgerufen werden, um externe Entities zu deaktivieren. Sie ist inzwischen als deprecated markiert, weil das neue Standardverhalten von libxml denselben Schutz bereits bietet.
4Können SVG-Dateien XXE-Angriffe enthalten?
Ja, SVG-Dateien sind vollwertige XML-Dokumente und können DOCTYPE-Definitionen mit externen Entities enthalten. Wird eine SVG-Datei serverseitig geparst, gelten dieselben Risiken wie bei jedem anderen XML-Import.
5Was ist ein Billion-Laughs-Angriff?
Dabei werden verschachtelte Entity-Definitionen so aufgebaut, dass sie beim Auflösen exponentiell expandieren und den Server durch Speicher- oder CPU-Erschöpfung lahmlegen, ohne dass externe Ressourcen benötigt werden.
6Reicht das Ablehnen von DOCTYPE-Definitionen als alleiniger Schutz?
Für die meisten fachlichen Formate wie Rechnungs- oder Produktimporte ja, da diese normalerweise keine Doctype benötigen. Ergänzend sollte trotzdem LIBXML_NONET gesetzt werden, um Netzwerkzugriff grundsätzlich auszuschließen.
7Gelten dieselben Risiken auch für SimpleXML?
Ja, SimpleXML nutzt dieselbe zugrunde liegende libxml-Bibliothek wie DOMDocument, weshalb dieselben Konfigurationsempfehlungen und Risiken gelten.
8Wie testet man eine Anwendung gezielt auf XXE?
Indem an jeden XML-verarbeitenden Endpunkt ein Dokument mit einer externen Entity gesendet wird, die auf eine bekannte, harmlose lokale Datei verweist, und geprüft wird, ob deren Inhalt in der Antwort erscheint.
9Welche Formate sind neben klassischem XML noch betroffen?
SVG, DOCX und andere auf XML basierende Dateiformate sowie SOAP-Nachrichten und XML-basierte Feed-Formate wie RSS und Atom sind ebenso potenziell betroffen.
10Wie hängt XXE mit SSRF zusammen?
Erlaubt der XML-Parser Netzwerkzugriff bei der Auflösung externer Entities, kann eine XXE-Schwachstelle genutzt werden, um Anfragen an interne Systeme zu stellen, was faktisch einem SSRF-Angriff entspricht.