XXE Preventie
Websecurity Zonder Nablussen
Webrisico is zelden mysterieus. Het zit meestal in voorspelbare fouten die onder tijdsdruk blijven staan.
Bij XXE Preventie zit de meeste winst in veilige defaults die in elke release automatisch worden afgedwongen.
Dat maakt security minder een losse controle achteraf en meer een standaardkwaliteit van je product.
Directe maatregelen (15 minuten)
Waarom dit telt
De kern van XXE Preventie is risicoreductie in de praktijk. Technische context ondersteunt de maatregelkeuze, maar implementatie en borging staan centraal.
Verdediging: hoe je XML-parsers hun tanden trekt
Na al dit geweld is het tijd om te praten over hoe je jezelf beschermt. En het goede nieuws is: de verdediging tegen XXE is relatief eenvoudig. Het slechte nieuws is dat “eenvoudig” niet hetzelfde is als “wordt gedaan”.
Stap 1: Schakel DTD-processing uit
De meest effectieve verdediging is het volledig uitschakelen van DTD-processing. Geen DTD’s, geen entities, geen probleem:
Python (defusedxml):
import defusedxml.ElementTree as ET
# Veilig - blokkeert external entities en DTD's
tree = ET.parse('input.xml')De defusedxml bibliotheek is een drop-in replacement
voor Python’s standaard XML-bibliotheken die standaard alle gevaarlijke
features uitschakelt.
Python (lxml):
from lxml import etree
parser = etree.XMLParser(
resolve_entities=False,
no_network=True,
dtd_validation=False,
load_dtd=False
)
tree = etree.parse('input.xml', parser)Java:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);PHP:
Stap 2: Gebruik geen XML als het niet hoeft
Dit klinkt als een open deur, maar het is verbazingwekkend hoe vaak XML wordt gebruikt terwijl JSON prima zou volstaan. JSON heeft geen entities, geen DTD’s, en geen external references. Het is saai, voorspelbaar, en veilig. Precies wat je wilt van een dataformaat.
Als je kunt kiezen tussen XML en JSON voor een nieuwe API, kies JSON. Als je XML moet ondersteunen voor backward compatibility, zorg dan dat de parser geconfigureerd is alsof XML een potentieel gevaarlijk dier is – want dat is het.
Stap 3: Valideer en sanitize
Als je XML moet accepteren:
- Blokkeer elk document dat een DOCTYPE-declaratie bevat
- Weiger documenten met SYSTEM of PUBLIC entities
- Beperk de entity-expansiediepte
- Stel een maximum in voor de grootte van geexpandeerde content (tegen Billion Laughs)
Stap 4: Netwerksegmentatie
Zelfs als een parser kwetsbaar is, beperkt netwerksegmentatie de impact. Als de webserver geen uitgaand verkeer mag initiëren (behalve naar specifieke backend-services), kan OOB-exfiltratie niet plaatsvinden. De parser leest misschien het bestand, maar de data komt nergens.
Dit is defense in depth: meerdere lagen beveiliging die elk op zich onvoldoende zijn, maar samen een solide verdediging vormen.
Het ongemakkelijke gesprek over XML-parsers
Laten we even eerlijk zijn. Het feit dat XML external entities standaard aanstaan in de meeste parsers is een van de meest absurde ontwerpbeslissingen in de geschiedenis van software. Het is alsof je een auto verkoopt waarvan de deuren standaard niet op slot gaan, en dan in de handleiding schrijft: “Vergeet niet de deuren op slot te doen.”
De XML-specificatie is van 1998. External entities waren een feature. Ze waren bedoeld voor documentbeheer in grote organisaties, voor het hergebruiken van tekst in technische documentatie, voor het modulair opbouwen van complexe XML- structuren. Nobele doelen, allemaal. Maar de mensen die de specificatie schreven, werkten in een wereld waarin XML-documenten afkomstig waren van vertrouwde bronnen. Interne systemen. Collega’s.
Ze hadden niet voorzien dat in 2026 elke willekeurige bezoeker van een website XML kan aanleveren aan een server. Ze hadden niet voorzien dat die XML zou worden geparsed door een component dat standaard alles vertrouwt. Ze hadden niet voorzien dat een feature bedoeld voor documentbeheer zou worden misbruikt om wachtwoordbestanden te stelen.
En toch, nu we het weten – al meer dan vijftien jaar – staan external entities nog steeds standaard aan in talloze parsers. De documentatie zegt “schakel dit uit in productie”. Ontwikkelaars lezen de documentatie niet. De parser functioneert prima zonder configuratie. Het XML-document wordt correct geparsed. De unittests slagen. En ergens op een server worden bestanden gelezen door iedereen die weet hoe je een DOCTYPE schrijft.
Het is de triomf van backwards compatibility over gezond verstand. Het is de reden waarom we penetratietesters nodig hebben. En het is de reden waarom dit hoofdstuk bestaat.
Samenvatting
XXE is een kwetsbaarheid die voortkomt uit vertrouwen – vertrouwen in de input, vertrouwen in de parser, vertrouwen in de standaardconfiguratie. Het is een herinnering dat features en kwetsbaarheden soms hetzelfde zijn, afhankelijk van wie de XML schrijft.
De verdediging is eenvoudig: schakel uit wat je niet nodig hebt. Vertrouw geen input. Configureer je parsers alsof elke XML die binnenkomt geschreven is door iemand die je kwaad wil doen. Want op een dag is dat zo.
Referenties
| Bron | URL |
|---|---|
| OWASP XXE Prevention Cheat Sheet | https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html |
| PortSwigger Web Security Academy – XXE | https://portswigger.net/web-security/xxe |
| PayloadsAllTheThings – XXE Injection | https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20Injection |
| defusedxml (Python) | https://github.com/tiran/defusedxml |
| W3C XML 1.0 Specification | https://www.w3.org/TR/xml/ |
| Billion Laughs Attack | https://en.wikipedia.org/wiki/Billion_laughs_attack |
Verder lezen in de kennisbank
Deze artikelen in het portaal geven je meer achtergrond en praktische context:
- API's — de onzichtbare lijm van het internet
- SSL/TLS — waarom dat slotje in je browser ertoe doet
- Encryptie — de kunst van het onleesbaar maken
- Wachtwoord-hashing — hoe websites je wachtwoord opslaan
- Penetratietesten vs. vulnerability scans
Je hebt een account nodig om de kennisbank te openen. Inloggen of registreren.
Gerelateerde securitymaatregelen
Deze artikelen bieden aanvullende context en verdieping: