在Java应用中,XML被广泛用于配置文件、接口报文和数据交换。如果解析XML时没有关闭外部实体加载,攻击者可以构造包含恶意DOCTYPE的XML,触发XXE漏洞,进而读取本地文件或探测内网。下面介绍具体的防护办法。

什么是XXE漏洞
XXE是指XML外部实体注入。XML规范允许在文档中定义外部实体,若解析器默认开启外部实体解析,攻击者就能通过实体引用让服务端加载敏感资源。例如以下恶意XML:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <foo>&xxe;</foo>
当不安全的解析器处理上述报文时,会把系统文件内容带入返回结果。
常见解析器的不安全用法
Java自带多种XML解析方式,下面列出几种容易出问题的写法。
- 使用DocumentBuilderFactory且不禁用DOCTYPE
- 使用SAXParserFactory默认配置
- 使用XMLInputFactory未设支持外部实体属性
安全设置方法
DocumentBuilderFactory防护
创建工厂后,应显式禁用DOCTYPE声明与外部实体。示例代码如下:
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
public class SafeXml {
public static DocumentBuilder getSafeBuilder() throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 禁用DOCTYPE
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);
return dbf.newDocumentBuilder();
}
}
SAXParserFactory防护
SAX方式同样需要关闭外部实体,可参考下面配置:
import javax.xml.parsers.SAXParserFactory;
public class SafeSax {
public static SAXParserFactory getSafeFactory() throws Exception {
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);
spf.setXIncludeAware(false);
return spf;
}
}
XMLInputFactory(StAX)防护
使用StAX解析时,通过设置属性阻止外部实体加载:
import javax.xml.stream.XMLInputFactory;
public class SafeStax {
public static XMLInputFactory getSafeFactory() {
XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
xif.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
return xif;
}
}
第三方库注意事项
像SAXReader等第三方工具也需手动配置。以org.dom4j为例:
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;
public class SafeDom4j {
public static SAXReader getSafeReader() throws SAXException {
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);
return reader;
}
}
总结建议
防止Java中的XXE漏洞核心就是禁止DTD并处理外部实体。开发时应统一封装安全的XML解析工具类,并在代码审查中检查是否使用了setFeature类安全设置。对来源不可信的XML一律采用严格解析策略,才能从根本上避免XXE风险。