Web安全基础篇——XXE外部实体注入

Web安全基础篇——XXE外部实体注入
AudienceXXE
XXE 是XML External Entity(XML外部实体注入)的英文缩写,是一种发生于XML解析时的漏洞,由于解析引擎并未对XML外部实体进行限制,导致攻击者可以通过注入恶意代码到XML中,致使服务器加载恶意的外部实体导致未授权的数据访问、服务拒绝攻击甚至执行远程代码等有危害的操作。XXE漏洞的危害主要有两个:文件读取、SSRF,在PHP环境且开启PECL上的Expect扩展可导致命令执行,故命令执行条件较为苛刻。
基础知识
XML
XML是一种类似于HTML (超文本标记语言)的可扩展标记语言,是用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML 文档结构包括XML声明、DTD 文档类型定义(可选)、文档元素。
XML语法规则
- 所有XMI元素必须有一个闭合标签
- XMI必须正确嵌套
- XML属性值必须加引号
- 实体引用
- 在XMI中,空格会被保留
- XMI标签对大小写敏感
DTD
DTD是文档类型定义的缩写,用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在另外一个单独的文件中(外部引用)。DTD是一种用来定义XML文档结构的文本文件,用来说明哪些元素/属性是合法的以及元素间应当怎样嵌套/结合,也用来将一些特殊字符和可复用代码段自定义为实体。DTD可以帮助浏览器或其他应用程序更好地解析和处理XML文档。
内部实体声明
内部的DOCTYPE声明的优点是可以使XML文档更具可移植性,因为不依赖于外部文件。但是内部的DOCTYPE声明会使XML文档变得较大,并且如果DTD定义很复杂,可能会使XML文档变得难以阅读和维护。
假如DTD被声明在XML源文件中,它应当通过下面的语法包装在一个DOCTYPE声明中:
1 | <!DOCTYPE 根元素 [元素声明]> |
例如:
1 | <?xml version="1.0" ?> <!-- xml文件的声明,版本8编码--> |
外部实体声明
外部DOCTYPE声明的优点是使XML文档更易于阅读和维护,因为DTD定义保存在单独的文件中,而不是嵌入在XML文档中。此外,外部的DOCTYP声明使得可以为多个XML文档使用相同的DTD定义。但是,外部的DOCTYPE声明的缺点是它依赖于外部文件,如果DTD文件丢失或损坏,XML 文档可能无法正确解析和处理。
当引用的DTD文件是本地文件的时候,用SYSTEM标识,并写上”DTD的文件路径”。
1 | <!ENTITY 实体名称 SYSTEM "URI/URL"> |
ELEMENT是关键字,是不能修改的
NAME表示元素名称
CONTENT是元素类型,必须要大写。CONTENT的内容有三种写法:
(1)EMPTY表示该元素不能包含子元素和文本,但可以有属性。
(2)ANY表示该元素 可以包含任何在该DTD中定义的元素内容。
(3)#PCDATA可以包含任何字符数据, 但是不能在其中包含任何子元素。
PCDATA
PCDATA的意思是被解析的字符数据。PCDATA是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。文本中的标签会被当作标记来处理,而实体会
被展开。被解析的字符数据不应当包含任何&
,<
或者>
字符,需要用&
、<
、 >
实体来分别替换。
CDATA
CDATA意思是字符数据,CDATA 是不会被解析器解析的文本,在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。
漏洞利用
XXE 和 SQL注入 的攻击方法也有一点相似,也分有回显和没有回显。有回显的情况可以直接在页面中看到payload的执行结果或现象,无回显的情况又称为 blind xxe(类似于布尔盲注、时间盲注),可以使用外带数据(OOB)通道提取数据。
读取文件
当应用对过用户上传的XML文件或POST请求进行数据进行XML解析,并且应用没有禁止XML引用外部实体,也没有过滤用户提交的XML数据,那么就存在XXE漏洞。
有回显的测试代码:
1 |
|
simple_load_string解析接收过来的XML代码。
payload1
1 |
|
payload2
1 | <!ENTITY xxe SYSTEM "file:///etc/passwd" > |
如果是无回显的文件读取,可以通过 blind XXE 方法加上外带数据通道(ooB)来提取数据。
先使用php://filter获取目标文件的内容,然后将内容以http请求发送到接受数据的服务器来读取数据。虽然无法直接查看文件内容,但我们仍然可以使用易受攻击的服务器作为代理,在外部网络上执行扫描以及代码。
SSRF
可以通过XXE进行SSRF攻击。
payload
1 | <?xml version="1.0" ?> |
命令执行
在php环境下,xml命令执行需要php装有expect扩展,但该扩展默认没有安装,所以一般来说命令执行是比较难利用,但不排除。搬运师傅们的代码以供参考。
1 |
|
payload
1 | <?xml version="1.0" encoding="utf-8"?> |
Dos攻击
常见的XML炸弹:当XML解析器尝试解析该文件时,由于DTD的定义指数级展开,这个1K不到的文件会占用到3G的内存。
1 | <?xml version="1.0"?> |
这个的原理就是递归引用,lol 实体具体还有 “lol” 字符串,然后一个 lol2 实体引用了 10 次 lol 实体,一个 lol3 实体引用了 10 次 lol2 实体,此时一个 lol3 实体就含有 10^2 个 “lol” 了,以此类推,lol9 实体含有 10^8 个 “lol” 字符串,最后再引用lol9。构造恶意的XML实体文件耗尽可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击。