Comment détecter et corriger les vulnérabilités liées aux entités XML
Michael Sherman
7 septembre 2022
0 minutes de lectureXML est un format texte lisible par l’humain, utilisé pour transporter et stocker des données structurées. Les balises et les structures de données sont définies par les utilisateurs dans des documents auto-descriptifs, analysables par tous les outils XML, ce qui offre aux développeurs un mécanisme hautement configurable pour représenter les données.
Pour compléter la syntaxe de base limitée de XML, un auteur peut définir la structure et le contenu autorisé des données d’un document à l’aide d’une définition de type de document (DTD). La DTD permet de définir les données valides d’un document et de les décrire à un seul endroit pour les réutiliser dans l’ensemble du document. Une entité générale est déclarée dans la DTD, puis référencée dans le corps du document en ajoutant une esperluette (&) devant son nom et un point-virgule (;) après.
Vous pouvez définir une entité dans le document :
Vous pouvez également déclarer une entité dans une source externe en indiquant un chemin de fichier ou une URL :
Le fichier person.dtd contient :
Associée à la syntaxe simple de XML et à l’uniformité de la plupart des analyseurs, cette fonctionnalité permet aux pirates de lancer relativement facilement une attaque appelée injection d’entité externe XML (XXE). Dans cet article, nous allons examiner de près les attaques XXE et découvrir comment les prévenir.
Pourquoi les attaques XXE représentent-elles un risque pour la sécurité ?
Les attaques par injection XXE permettent aux pirates d’exploiter les déclarations d’entités externes pour accéder à des fichiers ou à l’infrastructure du serveur ou du réseau ciblé. Il peut s’agir d’informations personnelles sensibles, de logique métier et d’identifiants.
Dans les cas les plus graves, les pirates peuvent lancer une falsification de requête côté serveur, qui leur permet d’usurper l’identité d’un serveur sur le réseau de leur cible et peut leur permettre d’exécuter du code à distance. Ils peuvent ainsi élever leurs privilèges, parcourir l’infrastructure de leur cible et attaquer d’autres composants non protégés — ou propager des attaques vers d’autres réseaux en faisant croire qu’elles proviennent de leur cible.
Récupération de données
La vulnérabilité par injection XXE la plus courante permet aux pirates d’amener un serveur à divulguer des données sensibles ou des fichiers dans une réponse HTTP. À elle seule, cette attaque donne à un pirate un accès en lecture seule aux données, mais elle peut révéler des informations utiles pour mener une attaque plus dommageable.
Par exemple, un pirate peut envoyer une charge utile à un serveur cible pour l’amener à afficher un fichier local contenant des mots de passe :
La mise en œuvre d’un protocole de chiffrement robuste est efficace pour empêcher la récupération de données, car elle rend les données stockées illisibles et inutilisables, même si un pirate parvient à infiltrer le serveur ciblé. En utilisant des algorithmes symétriques tels que l’Advanced Encryption Standard (AES) pour stocker et transférer des informations sensibles au format XML, vous définissez une clé de sécurité confidentielle qui servira à chiffrer et déchiffrer vos données.
En outre, désactiver la prise en charge par défaut des entités externes dans l’analyseur XML est une mesure efficace pour contrer ce type d’attaque.
Falsification de requête côté serveur
Un serveur vulnérable aux injections XXE permet à un pirate d’usurper l’identité du serveur et d’envoyer des requêtes à des ressources internes normalement invisibles depuis l’extérieur du réseau.
Lors d’une attaque par falsification de requête côté serveur (SSRF), un pirate injecte généralement une URL ou une adresse pointant vers le système de fichiers local du serveur vulnérable ou vers d’autres ressources à accès restreint — en particulier lorsque l’analyseur XML ne filtre pas correctement les entrées utilisateur. Il peut alors obtenir des identifiants et des privilèges d’administrateur sur le réseau ciblé :
Si le pirate parvient à obtenir des privilèges d’administrateur, il peut usurper l’identité du serveur pour sonder le réseau ciblé à la recherche d’autres vulnérabilités. Il peut même réussir à exécuter du code à distance et à propager d’autres attaques.
Voici quelques mesures qui améliorent considérablement la résilience de votre application face à ce type d’attaque :
Bloquez toutes les requêtes utilisateur non autorisées vers les ressources internes et les adresses confidentielles.
Envisagez de mettre en place une liste de blocage complète regroupant les adresses et URL potentiellement malveillantes susceptibles de menacer votre infrastructure Web.
Adoptez des outils d’analyse statique intelligents (comme Snyk Code) capables de rechercher les vulnérabilités et les failles de sécurité dans votre code.
Exécution de code à distance
Un pirate peut exploiter une injection XXE pour exécuter du code à distance (RCE) sur un serveur cible.
Par exemple, il peut cibler un site Web ou une application propulsé par PHP, sur lequel le plug-in Expect est activé, en déclarant une entité contenant le wrapper Expect afin d’exécuter des commandes à distance :
Dans cet exemple, la commande ifconfig renvoie la configuration réseau du serveur lorsque l’analyseur XML évalue l’entité xxe.
Nous pouvons empêcher l’exécution de code à distance en désactivant de manière sélective les wrappers de protocole, comme l’extension Expect de PHP, sur nos sites Web ou dans nos applications Web.
Toutefois, même lorsqu’il est impossible d’obtenir une réponse directe du serveur, un pirate peut recourir à des méthodes XXE aveugles.
Attaques XXE aveugles
Dans certains cas, les analyseurs XML peuvent empêcher les déclarations d’entités dans le corps des documents XML. Un pirate peut contourner cette restriction en utilisant des entités paramètre, qui ne sont déclarées que dans la DTD ou comme valeur d’une autre entité. Une entité paramètre se déclare en faisant précéder son nom d’un signe pourcentage et d’un espace (%), puis se référence en ajoutant un signe pourcentage (%) devant son nom et un point-virgule (;) après.
Avec ce code, le serveur ciblé tentera d’envoyer la requête HTTP à l’URL du serveur du pirate. Ce dernier peut ainsi effectuer une recherche DNS sur le serveur ciblé à l’aide de cette attaque XXE aveugle.
Divulgation d’informations basée sur les erreurs
Notre serveur est vulnérable aux méthodes d’injection XXE aveugles si un pirate peut récupérer des données précieuses en examinant les messages d’erreur qu’il émet.
Par exemple, cette charge utile contraint notre serveur à divulguer le fichier /etc/pâsswd dans son message d’erreur :
Cette charge utile définit trois entités paramètre : badfile, qui contient le contenu du fichier /etc/pâsswd ; wrapper, qui contient la déclaration dynamique d’une nouvelle entité paramètre appelée induce ; et l’entité induce, qui déclenche une recherche sur un chemin provoquant un message d’erreur.
Pour déclarer l’entité wrapper, le pirate déclare dynamiquement l’entité induce, qui contient un chemin valide mais inexistant, incluant la valeur du paramètre badfile. Ensuite, lorsque l’entité wrapper est référencée, la déclaration dynamique de l’entité induce est lancée.
Enfin, lorsque l’analyseur rencontre l’entité induce, il renvoie un message d’erreur indiquant à l’utilisateur que le fichier dont le nom correspond à la valeur de badfile n’existe pas dans le chemin nosuchfileexists. Comme badfile contient le contenu de etc/pâsswd, le pirate peut voir ces informations.
Un protocole robuste de gestion des erreurs peut réduire la vulnérabilité de notre application à la divulgation d’informations basée sur les erreurs. Il peut notamment limiter la longueur et la portée des messages d’erreur envoyés par le serveur au client. En utilisant un corps de message personnalisé et un code d’état HTTP, nous pouvons éviter les messages d’erreur détaillés générés automatiquement, qui fournissent gratuitement aux pirates des informations utiles à leurs reconnaissances.
Nous devons définir clairement les messages d’erreur pour les scénarios prévus, comme ceux correspondant à l’exception FileNotFound de notre serveur d’exemple. Nous devons également prévoir des messages d’erreur adaptés aux cas particuliers, ce qui nécessite généralement de tester notre code.
Exfiltration hors bande
Une attaque hors bande permet d’exfiltrer des données par un canal différent de celui utilisé pour envoyer l’attaque. Elle consiste généralement à amener le serveur ciblé à envoyer une requête à une adresse hébergeant une DTD externe malveillante contrôlée par le pirate.
Le pirate doit d’abord envoyer une charge utile compromise contenant le contenu d’une DTD malveillante, par exemple :
Le fichier corrupted.dtd hébergé sur le serveur du pirate contient :
Lorsque l’entité revealinfo est exécutée, une requête HTTP est envoyée au serveur du pirate. La valeur de badfile est intégrée à la chaîne de requête.
Lorsque l’entité deval est référencée, la déclaration dynamique de l’entité revealinfo est lancée.
Autres vecteurs d’attaque
Parmi les autres vecteurs courants des attaques XXE, on trouve :
Les téléversements de fichiers, comme les fichiers
.configLes champs de saisie de texte, en particulier les champs HTML
textettextarea, dont les règles de validation des entrées peuvent être limitéesLes technologies basées sur XML, comme les flux RSS et les API
Les fichiers basés sur XML, en particulier les formats courants comme les images SVG
Par exemple, un pirate peut téléverser un fichier SVG contenant un lien vers un document malveillant afin de lancer une attaque par bombe XML :
La charge utile pourrait ressembler à ceci :
L’analyseur repère plusieurs déclarations d’entités dans la DTD, mais ne les évalue pas immédiatement. Il lit ensuite le document et rencontre l’élément bin, qu’il appelle en développant l’entité a4. Pour cela, il doit développer les dix instances contenues de l’entité a3, ce qui l’oblige à développer les entités a2 qu’elles contiennent — jusqu’à a0.
La taille finale de l’élément bin après développement correspond au développement récursif de tous les éléments de l’entité a4. Dans une charge utile comportant dix niveaux ou plus d’entités imbriquées, le fichier obtenu peut atteindre plusieurs centaines de gigaoctets. Cela provoque généralement une erreur de mémoire insuffisante sur le serveur qui tente d’analyser le fichier SVG, et entraîne un déni de service pour nos utilisateurs.
La mise en place de limites automatiques de mémoire ou d’utilisation d’autres ressources pour le traitement des requêtes suffit à prévenir de nombreux types d’attaques par déni de service, qui visent généralement à saturer les capacités d’un serveur.
Bonnes pratiques de sécurité applicables à tous les cas
Désactiver la prise en charge des entités externes
Interdire les entités externes et les DTD définies par l’utilisateur suffit souvent à atténuer de nombreux types d’attaques par injection XXE. La plupart des outils proposent une commande simple pour y parvenir.
Utiliser un pare-feu pour applications Web (WAF)
Les pare-feu pour applications Web (WAF) sont très efficaces contre les attaques XXE en général : ils inspectent le trafic HTTP à la recherche de contenus potentiellement malveillants et appliquent des règles de filtrage pour protéger nos applications Web.
Mettre en œuvre une sécurité Zero Trust
La relation de confiance entre vos applications Web et les services externes ou tiers (comme les brokers de messages et les plateformes d’authentification des utilisateurs) peut être exploitée pour lancer une attaque SSRF contre votre infrastructure serveur. En outre, les services de votre réseau ne doivent pouvoir accéder qu’aux ressources nécessaires à leur bon fonctionnement.
Nous devons veiller à isoler correctement les journaux et les données sensibles, et mettre en place des processus rigoureux pour auditer régulièrement les privilèges d’accès de tous les utilisateurs, qu’ils soient humains ou programmatiques. Cela facilite également la gestion de la maintenance de la sécurité à long terme.
Toujours lancer des analyses automatisées et des tests de vulnérabilité XXE
Les analyses de vulnérabilités XXE automatisées permettent de détecter et de corriger les vulnérabilités de votre infrastructure avant qu’un pirate ne les exploite. Un système de détection complet et intelligent doit également proposer des recommandations pour renforcer davantage la sécurité du système.
Maintenir vos correctifs de sécurité à jour
Il est important que nos systèmes disposent des correctifs les plus récents fournis par des prestataires de sécurité de confiance. Ces correctifs peuvent inclure des mises à jour de pilotes de sécurité et des correctifs de protection contre les attaques par déni de service. Pour connaître les dernières vulnérabilités open source, nous vous recommandons d’utiliser Snyk Open Source, qui s’appuie sur la Snyk Vulnerability Database, exhaustive, précise et à jour.
Réduisez les risques grâce aux capacités de protection de Snyk
Les bibliothèques tierces présentent parfois des vulnérabilités exploitables, ce qui expose votre application aux attaques. Pour renforcer davantage ses défenses, nous vous conseillons d’utiliser Snyk OSS afin d’analyser chaque bibliothèque tierce intégrée à votre application.
Vous pouvez également tirer parti des fonctionnalités de Snyk Code pour détecter les failles de sécurité potentielles avant qu’elles ne soient exploitées.
En conclusion sur la sécurité XML
XML est un outil polyvalent et puissant pour le transport des données, d’autant plus qu’il permet d’utiliser dynamiquement des ressources externes liées. Toutefois, ces caractéristiques en font un outil prisé des acteurs malveillants. Pour prévenir et atténuer efficacement les risques associés, il est essentiel de comprendre les vulnérabilités potentielles qu’il peut introduire.
Des entrées utilisateur mal assainies, une gestion des erreurs trop détaillée et des privilèges d’accès mal configurés peuvent permettre aux attaquants de compromettre nos systèmes au moyen d’attaques par injection d’entités externes (XXE). Pour corriger efficacement ces vulnérabilités, validez et filtrez les entrées utilisateur et les fichiers téléversés. Dans la plupart des cas, il suffit de supprimer des fonctionnalités telles que le traitement des DTD externes ou les wrappers de protocole PHP.
Les messages d’erreur sont plus adaptés lorsqu’ils communiquent le moins d’informations possible à l’utilisateur. Par exemple, si une tentative de connexion échoue, il n’est pas nécessaire de préciser si le mot de passe ou le nom d’utilisateur est incorrect.
Vous pouvez également mettre en place des WAF et des protections contre les attaques par déni de service (DoS), ou faire appel à un fournisseur qui propose ces fonctionnalités. Et si un attaquant parvient à franchir vos défenses, il ne devrait trouver que des données chiffrées et un réseau de services fondé sur le modèle Zero Trust.
Lancez-vous dans les compétitions Capture The Flag
Apprenez à résoudre des défis Capture The Flag en regardant à la demande notre atelier virtuel d’initiation.



