Une XXE (XML External Entities) est une vulnérabilité faisant partie du Top 10 de l’OWASP et touchant les programmes interprétant le XML.
Elle se caractérise par la possibilité de lire des fichiers sur le serveur cible. Elle peut ainsi mettre en danger celui-ci, en accédant, par exemple, à un fichier de configuration contenant des mots de passe, en copiant les fichiers de la base de données ou en récupérant le code source d’une application.
XML et entités
Le XML (eXtensible Markup Language) est un métalangage de balisage, autrement dit, un moyen de formaliser du texte. Il est reconnaissable par son utilisation des chevrons et son extensibilité, permettant ainsi d’ajouter de nouvelles balises dès que voulu.
Voici un exemple d’un fichier XML qui sert à formater un menu de petit-déjeuner :
Une des fonctionnalités du XML nous intéresse particulièrement dans notre cas : les entités.
Une entité est, globalement, l’équivalent XML d’une variable et permet de définir des éléments que l’on pourra placer ensuite ailleurs.
Reprenons notre menu précédent ; si nous souhaitons que la devise du prix puisse être facilement modifiable, nous pouvons utiliser une entité comme ceci :
Lors de la lecture de ce fichier XML, toutes les instances de « ¤cy » seront remplacées par la valeur définie dans la balise ENTITY, ce qui nous donne ce résultat :
Une particularité des entités est qu’il est possible de faire référence à une entité dite « externe » (c’est-à-dire externe au document, un fichier soit local, soit situé sur un serveur distant) en rajoutant « SYSTEM » lors de la définition de l’entité. Par exemple, si l’on souhaite faire référence à une photo de pancake située dans notre dossier /photos, nous pourrions définir l’entité suivante : <!DOCTYPE breakfast_menu [ <!ENTITY pancakePhoto SYSTEM « file:///photos/pancake.jpg » > ]>
Et c’est là que se situe le cœur d’une XXE.
Fonctionnement d’une XXE
Il est commun que certains sites web se servent de données utilisateurs pour créer des fichiers XML (ou reposant sur du XML, tel que des PDF), avant de renvoyer ceux-ci à l’utilisateur.
Il est donc possible pour un utilisateur malveillant d’essayer d’injecter dans le code XML des références à des entités externes, notamment des fichiers sensibles se situant sur le serveur. Puisque c’est le serveur qui va lire le XML, il va essayer de résoudre les entités externes avant de les incorporer au document final, qui sera ainsi renvoyé au client en contenant des données sensibles.
Par exemple, si le serveur tente de créer un menu de petit-déjeuner à partir du XML suivant :
Le document généré par ce code XML incorporera le fichier /etc/passwd du serveur l’ayant exécuté (si celui-ci est vulnérable aux XXE, bien évidemment).
Pour être vulnérable, un service doit inclure trois comportements :
- Il doit être possible pour un utilisateur de manipuler du contenu XML qui sera ensuite parsé par le serveur. Cela peut se faire via un upload de fichier, un éditeur de texte (autorisant des formats XML) ou la réutilisation de données provenant du client dans un champ XML (par exemple les noms et prénoms, une adresse, ou un email).
- Le parseur XML autorise la définition et l’utilisation d’entité.
- Le parseur XML doit parser et interpréter les références externes dans les entités.
Note complémentaire :
Il existe un autre type d’attaque faisant appel aux entités (non externes cette fois-ci) XML : les XEE (XML Entity Expansion).
C’est une attaque par déni de service qui consiste à créer des milliards de références à des entités, ce qui consomme beaucoup de ressources et peut ralentir, voire bloquer, un système.
Exemple :
L’entité a7 contient 10 fois l’entité a6, qui contient elle-même 10 fois l’entité a5, etc. Et cela exponentiellement, jusqu’à l’entité a0 qui n’est qu’une simple chaine de caractères.
Cette attaque passe par les mêmes vecteurs qu’une XXE, la seule différence notable étant qu’elle n’utilise pas de référence externe, ce qui fait qu’interdire les entités externes tout en laissant possible la définition d’entités « standards » vous laisse vulnérable.
Impact et protection d’attaques XXE
L’impact d’une XXE peut être dévastateur : étant donné qu’elle permet d’extraire les fichiers du serveur web, elle rend possible :
- L’extraction du code source de l’application.
- Le vol de clés d’API, de mots de passe stockés en dur, etc. En soi, toute donnée ou tout mot de passe stocké dans un fichier de configuration.
- Le vol de base de données : il est possible de copier entièrement les fichiers contenant la base de données. C’est particulièrement le cas pour des bases « mono-fichier » comme sqlite.
- Le vol de fichiers générés ou uploadés par d’autres utilisateurs et stockés sur le serveur. Cela peut être particulièrement gênant si ceux-ci contiennent des données personnelles (factures, papiers d’identité, données médicales…).
Pour se protéger des XXE, il suffit de retirer l’un des trois comportements cités précédemment :
- Ne pas utiliser de données utilisateurs dans les documents XML. Cette option peut être viable si les données dynamiques des documents sont indépendantes des utilisateurs (par exemple une date). Le code XML en lui-même ne doit JAMAIS transiter par le client.
- Interdire la définition d’entités ou d’entités externes. La plupart des interpréteurs XML incluent ce genre d’options, que ce soit lors de la configuration, de l’initialisation ou de l’utilisation. Lisez attentivement la documentation de votre interpréteur pour savoir comment le configurer et le sécuriser.
Essayer de « nettoyer » les données utilisateurs avant de les utiliser peut être tentant, mais c’est une entreprise risquée, car il est difficile de prendre en compte tous les cas d’utilisations.
En conclusion, les XXE sont des vulnérabilités assez méconnues et dont l’impact peut être très grave. La versatilité du XML (présent dans des fichiers .pdf, .docx, .svg, .xlsx…) peut rendre difficile leur détection, y compris pour les propriétaires du site eux-mêmes. Heureusement, une fois le risque identifié, sa prévention est (généralement) facile et efficace.