介紹XXE漏洞
XML外部實體注入(XML External Entity)簡稱XXE漏洞,XML用於標記電子文件使其具有結構性的標記語言,可以用來標記數據、定義數據類型,是-種允許用戶對自己的標記語言進行定義的源語言。XML文檔結構包括XML聲明、DTD文檔類型定義(可選)文檔元素。
常見的XML語法結構如下圖所示。
<!--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)可以是內部聲明也可以引用外部DTD,如下所示。
- 內部聲明DTD格式: <! DOCTYPE 根元素 [元素聲明] >。
- 引用外部DTD格式: <! DOCTYPE 根元素 SYSTEM "文件名">。
在DTD中進行實體聲明時,將使用ENTITY關鍵字來聲明。實體是用於定義引用普通文本或特殊字符的快捷方式的變量。實體可在內部或外部進行聲明。 - 內部聲明實體格式: <! ENTITY 實體名稱 "實體的值">。
- 引用外部實體格式: <! ENTITY 實體名稱 SYSTEM "URI">。
XXE漏洞攻擊
http請求的POST參數如下所示:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY b SYSTEM "file:///c:/kms10.log">
]>
<xml>
<xxe>&b;</xxe>
</xml>
在POST參數中,關鍵語句為file///windows/win.ini",該語句的作用是通過filet協議讀取本地文件C:/windows/win.ini, 如圖所示。
好吧我沒做出來,因為libxml2.9.0以后,默認不解析外部實體,導致XXE漏洞逐漸消亡。如果想做這個實驗可以照下面這個鏈接玩玩。
https://github.com/vulhub/vulhub/tree/master/php/php_xxe
XXE漏洞代碼分析
<?php
//libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile);
$xml = simplexml_import_dom($dom);
print_r($xml);
$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引入外部實體,所以當我們創建一個包含外部實體的XML時,外部實體的內容就會被執行。
修復建議
禁止使用外部實體,例如libxml disable_entity_loader(true) 。
過濾用戶提交的XML數據,防止出現非法內容。