Rappel théorique

Une faille XXE (XML External Entity) survient lorsqu'une application analyse un document XML fourni par l'utilisateur avec un parseur configuré pour résoudre les entités externes et le DTD (Document Type Definition). Un attaquant peut alors déclarer ses propres entités pour faire lire des fichiers locaux, effectuer des requêtes réseau internes (SSRF) ou provoquer un déni de service.

Exemple de payload

<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///var/www/html/OWASP/A04-XXE/secret.txt">
]>
<produit>
  <nom>&xxe;</nom>
</produit>

Si le parseur résout l'entité &xxe;, le contenu du fichier secret.txt est inséré dans le document XML puis renvoyé à l'utilisateur, alors que rien dans la donnée XML ne devrait permettre de lire un fichier du serveur.

Code vulnérable (PHP / DOMDocument)

$dom = new DOMDocument();
$dom->loadXML($xmlEnvoyeParUtilisateur, LIBXML_NOENT | LIBXML_DTDLOAD);

Les options LIBXML_NOENT (substitue les entités par leur valeur) et LIBXML_DTDLOAD (charge le DTD externe déclaré) sont précisément ce qui permet l'attaque XXE ci-dessus.

Conséquences

Mesures de protection

Démo vulnérable

Un formulaire permet d'envoyer un document XML, analysé avec LIBXML_NOENT | LIBXML_DTDLOAD : une entité externe permet de lire secret.txt sur le serveur.

Accéder à la démo vulnérable

Démo sécurisée

Même formulaire, mais analysé sans les options dangereuses (comportement par défaut de PHP 8) : l'entité externe n'est pas résolue et le contenu du fichier n'apparaît jamais dans la réponse.

Accéder à la démo sécurisée