Thijmen Kooy

Wat is een XXE-injectie?

Hoe hackers XML eXternal Entities misbruiken

In veel webapplicaties wordt XML gebruikt om data te structureren. De XML-standaard is in 1996 in het leven geroepen door het World Wide Web Consortium (W3C) en is lange tijd zeer populair geweest. Er is echter veel meer mogelijk met XML dan veel ontwikkelaars weten, waardoor misbruik door hackers soms mogelijk is.

Het onzorgvuldig gebruik van XML-functies kan meerdere kwetsbaarheden introduceren. Een van deze kwetsbaarheden is XML External Entity Injection (afgekort: XXE Injection). Dit betekent dat een aanvaller data kan uitlezen uit bestanden van het lokale bestandssysteem, of kan er data worden opgehaald van interne URL’s. Dit kan de aanvaller doen door middel van een referentie in de XML. De software die de XML moet verwerken interpreteert deze referenties wat de software dus kwetsbaar maakt. Ook het laten vastlopen van de server, of in het ergste geval, commando’s uitvoeren op het onderliggende systeem, behoort soms tot de mogelijkheden. 

De XXE-kwetsbaarheid staat in de kwetsbaarheden top 10 van OWASP. Dit betekent deze kwetsbaarheid wordt erkend als een van de meest kritieke beveiligingsproblemen. Deze kwetsbaarheid valt onder de categorie A05:2021-Security Misconfiguration’ en staat op plek 5

XML-basics

XML, ook wel bekend als Extensible Markup Language, is net zoals HTML gebaseerd op Standard Generalized Markup Language (SGML). Een XML-bestand bestaat, net zoals HTML, uit declaraties, elementen en attributen. In de afbeelding hieronder wordt afgebeeld hoe een XML-bestand is opgebouwd.

1

Een XML-bestand begint met de XML declaration, die aangeeft dat het om XML gaat, en welke versie van XML. Dit is eigenlijk altijd <?xml version="1.0"?>.

Vervolgens wordt gedefinieerd hoe de data in het bestand moet worden gestructureerd. Dit heet de Document type declaration. Dit gebeurt in een speciaal element met de naam <!DOCTYPE ...>. Hierin kan de auteur van de XML tussen blokhaken [ ... ] een definitie geven, of verwijzen naar een apart bestand met de extensie .dtd, lokaal of met een URL. Op het internet bestaan veel standaard DTD’s die via een URL geïmporteerd kunnen worden.

Hierna volgt de data, gestructureerd in elementen met attributen, waarin gebruik kan worden gemaakt van entiteiten.

Entiteiten in XML

Entiteiten kunnen worden vergeleken met een variabele zoals in programmeertalen. In het onderstaande voorbeeld wordt de waarde Hello World” in de entiteit msg opgeslagen, en wordt de waarde daarvan in het element <message> gezet. De referentie naar de waarde van msg wordt geschreven als &msg;. Zoals je ziet wordt de entiteit gedeclareerd in de Document Type Declaration (DTD), binnen het element <!DOCTYPE ...>.

<!DOCTYPE xml [ <!ENTITY msg "Hello World"> ]> <xml> <message>&msg;</message> </xml>

Externe entiteiten

Het bovenstaande is een voorbeeld van een interne entiteit. De XXE-aanval maakt gebruik van een externe entiteit. Het sleutelwoord SYSTEM geeft aan dat de DTD extern is gedefinieerd. Hierbij refereert de entiteit ext naar de externe bron https://example.com/, en zal bij het interpreteren van de XML worden geraadpleegd. Hiervan wordt onderstaand een voorbeeld gegeven.

<!DOCTYPE xml [ <!ENTITY ext SYSTEM "http://example.com/" > ]> <xml> <site>&ext;</site> </xml>

Buiten het opvragen van externe sites kunnen er ook bestanden worden opgevraagd op het bestandssysteem.

XXE-aanval

Een XXE-aanval is dus mogelijk als een applicatie XML-invoer accepteert en externe entiteiten ondersteunt. Om deze XXE-aanval te demonstreren heeft Joshua Barone een testomgeving opgezet. Deze omgeving is gemaakt om dit soort aanvallen te testen en is daarom opzettelijk kwetsbaar voor deze aanval. Deze applicatie bevat een aanmeldformulier waar gebruik wordt gemaakt van XML. In de onderstaande afbeelding zie je dat het element <email> terugkomt in het antwoord. 

6

Om te kijken of de XML-functionaliteit entiteiten ondersteunt, wordt er allereerst een lokale entiteit getest. Dit wordt gedaan door de volgende regel toe te voegen:

<!DOCTYPE foo [ <!ENTITY xxe "Dit is een lokale entiteit" >]>

Aangezien de waarde van <email> wordt terug gegeven in het antwoord, wordt daar de entiteit aangeroepen. Zoals is afgebeeld, wordt de waarde van de entiteit xxe, en dus de waarde Dit is een lokale entiteit” weergegeven in het antwoord.

5

Om een XXE-aanval uit te voeren wordt er nu een externe entiteit aangemaakt met de volgende regel:

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd" >]>

Deze externe entiteit verwijst naar het bestand /etc/passwd op het lokale bestandssysteem van de applicatie. Aangezien de waarde van <email> wordt teruggegeven in het antwoord, wordt daar de externe entiteit aangeroepen. Zoals is afgebeeld wordt de waarde van de entiteit xxe, en dus de inhoud van /etc/passwd weergegeven in het antwoord.

4

Wat kan je nog meer met XXE?

Een XXE kan buiten de genoemde voorbeelden worden gebruikt voor andere aanvallen. Zo kan er een XXE worden gebruikt om een DoS-aanval uit te voeren met een Billion Laughs-aanval. Bij deze aanval worden heel veel kopieën gemaakt van een entiteit, wat ervoor zorgt dat het betreffende programma soms wel 3 gigabyte aan geheugen moet gebruiken om de XML te verwerken.

In sommige gevallen kan een XXE ook worden gebruikt voor port scanning door referenties te maken naar het interne netwerk. Een XXE kan in sommige gevallen er ook voor zorgen dat commando’s kunnen worden uitgevoerd op het onderliggende systeem.

Oplossen van XXE-kwetsbaarheden

De meeste XXE-kwetsbaarheden ontstaan doordat de applicatie gevaarlijke functies ondersteunt zoals externe XML-entiteiten. De meeste effectieve manier om deze kwetsbaarheden te verhelpen is door deze functies uit te zetten en door de applicatie te beperken door het filteren van gebruikersinvoer. XXE kan worden voorkomen met de volgende configuratieregels:

  • Java – javax.xml.parsers.DocumentBuilderFactory
    • factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
  • PHP – libxml2
    • libxml_set_external_entity_loader(null);
  • .NET –XmlTextReader
    • reader.ProhibitDtd = true;

Voor andere platformen of programmeertalen, zie de OWASP XXE Prevention cheatsheet. Veel talen en libraries zijn tegenwoordig beschermd tegen XXE-aanvallen omdat het gebruik van externe entiteiten standaard wordt geblokkeerd. 

Het gebruik van een vaste lokale DTD kan ook helpen in het afdwingen van een correcte en veilige XML-invoer. In een DTD staat hoe de invoer van de gebruiker eruit moet zien en waar aan het moet voldoen. Daarnaast mag de applicatie ook geen DTD accepteren die de gebruiker aanlevert.

Het is ook de moeite waard om andere formaten zoals JSON en YAML te overwegen. Maar kijk uit, ook bij deze formaten geldt dat gevaarlijke implementaties of gevaarlijke functionaliteiten kwetsbaarheden kunnen introduceren.