XXE
1. 發現點
聯繫表單(Contact Form):使用者提交的訊息可能被XML解析
ALL XML
文件上傳功能:應用允許上傳XML格式的文件,例如SVG、DOCX(ZIP包內含XML)
API請求(REST/SOAP):部分API使用XML作為請求格式
SSO(單點登入):某些SSO協議(如SAML)使用XML格式傳遞身份驗證數據
使用
<!DOCTYPE>定義實體來確認伺服器是否解析:<!DOCTYPE email [ <!ENTITY test "XXE Test"> ]> <email> &test; </email>如果伺服器回應包含
XXE Test,代表存在XXE漏洞。Example
POST /submitDetails.php HTTP/1.1 Host: 10.129.59.193 User-Agent: Mozilla/5.0 (X11; Linux aarch64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Content-Type: text/plain;charset=UTF-8 Content-Length: 214 Origin: http://10.129.59.193 Connection: keep-alive Referer: http://10.129.59.193/ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE email [ <!ENTITY company SYSTEM "file:///etc/passwd"> ]> <root> <name>hack</name> <tel>4324324</tel> <email>&company;</email> <message>hackyou</message> </root>
2. 測試Payload
🔹 讀取伺服器上的敏感文件
目標:讀取Linux系統的
/etc/passwd,如果成功,代表伺服器允許訪問本地文件系統。應對方式:如果無法回顯數據,嘗試
php://filter/進行Base64編碼讀取。
🔹 讀取應用程式代碼
目標:以Base64格式讀取
index.php,然後手動解碼,分析應用的後端邏輯。
🔹 進行內網探測
目標:確認內網服務是否可訪問,進一步發動SSRF攻擊。
3. 不符合 XML 格式
⭐ 問題背景:
當目標網站會返回 XML 響應,但返回內容必須符合 XML 格式時,如果我們直接插入外部實(例如檔案內容),裡面可能會有符號造成 XML 格式錯誤,這會導致回顯失敗。
解決方法:
用 <![CDATA[ ]]> 包裹檔案內容,使其被當成「純文本」處理,這樣就不怕 XML 格式被破壞。
⭐ 繞過方法 1 — CDATA 包裝
在 DTD 文件中預先定義好:
最後在 XML 裡調用 &joined; ,伺服器返回內容就會被包在 <![CDATA[ ]]> 裡。
⭐ 繞過方法 2 — Parameter Entities(參數實體)
普通
ENTITY是&xxe;參數實體 是
%xxe;,只能在 DTD 裡用它最大的用途: 你可以把
%xxe;放在外部 DTD 文件,讓目標伺服器去你主機下載.dtd,然後讀取本地文件內容,最後連接成 XML 安全格式輸出。
⭐ 操作流程範例
✅ 1. 本地建立 xxe.dtd 檔案:
注意最後一行等於告訴 XML「先引入 begin、file、end 三個實體,再合併成一個叫 joined」的最終實體。
✅ 2. 啟動 HTTP 伺服器讓目標伺服器來抓:
此時伺服器在
http://你的IP:8000/xxe.dtd提供下載。
✅ 3. 向目標提交 payload:
這時候目標伺服器會去你機器下載
xxe.dtd,然後讀取submitDetails.php檔案並回顯。結果會被包在
<![CDATA[ 文件內容 ]]>裡面,避開 XML 格式限制。
4. 基於錯誤的XXE
⭐ 問題背景
有時目標網站:
不在 XML 響應中顯示實體結果
不會回傳你控制的內容
但如果伺服器會顯示解析錯誤(error), 我們就可以透過「故意出錯」 把檔案內容注入錯誤訊息中回顯出來! 這就叫做 Error-based XXE 或 錯誤型 XXE。
⭐ 利用條件:
目標網站不顯示 XML 實體內容。
但它會在 XML 格式錯誤時返回錯誤訊息(如 PHP Warning)。
我們可以透過設計 payload, 把本地檔案內容夾帶進錯誤訊息裡。
⭐ 攻擊思路:
我們故意參考一個不存在的實體
%nonExistingEntity;。同時把
file實體拼接在錯誤內容中, 讓錯誤訊息中顯示「找不到實體」, 而這個「錯誤提示」會同時帶出我們指定的本地檔案內容。
⭐ 操作流程範例:
✅ 1️⃣ 建立本地 xxe.dtd:
xxe.dtd:解釋:
%file;會包含/etc/hosts文件內容%nonExistingEntity;是刻意寫不存在的伺服器在解析
%error;時 → 會「找不到 nonExistingEntity」並拋出錯誤 → 錯誤訊息中會包含%file;的內容
✅ 2️⃣ 啟動 HTTP 伺服器供目標訪問:
✅ 3️⃣ 傳送 Payload 給目標:
目標伺服器會從你的
xxe.dtd檔案讀取內容再觸發錯誤訊息
錯誤訊息中就會包含
/etc/hosts檔案內容!
5. OOB 資料外洩
⭐ 問題背景
在部分目標系統中:
沒有 XML 回顯
不會在頁面上顯示任何錯誤
也無法利用錯誤型 XXE 看結果
⭐ 利用條件:
目標存在 XXE 漏洞。
目標不會把檔案內容顯示在回應中(無回顯)。
目標不會顯示 XML 錯誤訊息(無錯誤型 XXE)。
伺服器允許向外發送 HTTP 請求或 DNS 請求。
⭐ 攻擊思路:
我們建立一個外部 DTD 檔案。
讓伺服器讀取本地檔案內容(例如
/etc/passwd)。將這些內容嵌入到一個
http://你的伺服器/?data=檔案內容的請求中。伺服器自動向我們的 HTTP server 發送請求。
在我們的 HTTP server 日誌裡就能看到檔案內容(Out-of-band 外洩成功)。
⭐ 操作流程範例:
✅ 1️⃣ 建立外部 DTD (xxe.dtd)
xxe.dtd)說明:
%file;:從伺服器讀取/etc/passwd檔案內容%exfil;:定義send實體,讓伺服器用 HTTP 發送資料
✅ 2️⃣ 啟動本地 HTTP 伺服器:
等待伺服器連回來
✅ 3️⃣ 發送 XXE Payload 給目標:
伺服器解析
%remote;下載你的 DTD執行
%file;讀取內容自動透過 HTTP 請求發送資料到你的主機
✅ 4️⃣ 觀察結果
在本地 server 日誌中你會看到:
data=參數裡就是/etc/passwd內容。
6. 連鎖XXE漏洞
🔹 XXE + SSRF
若應用允許訪問內部服務,我們可以透過XXE進行SSRF攻擊,如請求AWS Metadata:
如果成功,可能獲取雲端伺服器的憑據,進一步控制伺服器!
🔹 XXE + RCE(遠端代碼執行)
如果應用允許解析DTD,則可以透過內部Java類調用命令:
evil.dtd 內容:
這將會透過外部HTTP請求洩露
/etc/passwd的內容,可進一步嘗試RCE。
🔹 XXE + DoS(拒絕服務攻擊)
Billion Laughs Attack(遞歸炸彈)導致伺服器崩潰:這樣會導致伺服器無限解析,進而崩潰(DoS)。
6.Skills Assessment
最后更新于
这有帮助吗?