怎么在Java中防止XML外部实体注入(XXE)攻击

来源:PHP编程网作者:落伍者头衔:草根站长
导读:本期聚焦于小伙伴创作的《怎么在Java中防止XML外部实体注入(XXE)攻击》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《怎么在Java中防止XML外部实体注入(XXE)攻击》有用,将其分享出去将是对创作者最好的鼓励。

XXE攻击的基本原理

XML外部实体注入(XXE)的核心是利用XML规范中的外部实体声明功能,攻击者在XML中自定义外部实体,指向本地文件或内网地址,当应用解析该XML时,会按照实体定义读取对应内容并返回,造成信息泄露或内网探测。比如恶意XML可以定义实体读取/etc/passwd文件,解析后该文件内容就会被攻击者获取。

怎么在Java中防止XML外部实体注入(XXE)攻击

Java中常见的XXE风险场景

Java生态中有多种XML解析方式,很多默认配置下都允许解析外部实体,常见风险场景包括:

  • 使用DocumentBuilderFactory解析用户上传的XML文件
  • 使用SAXParserFactory处理外部传入的XML数据
  • 使用XMLInputFactory(StAX)解析XML流
  • 使用第三方库如Jackson、XStream解析包含XML格式的数据

防范XXE的核心方案

1. 禁用外部实体和DTD

最彻底的防护方式是禁用XML的外部实体解析和DTD(文档类型定义)功能,因为外部实体必须依赖DTD声明。不同解析工厂的配置方式略有差异,但核心逻辑都是关闭相关特性。

2. 限制XML解析的扩展功能

除了禁用外部实体,还可以限制XML解析的通用实体扩展、参数实体扩展等功能,进一步缩小攻击面。

3. 使用安全的解析配置模板

可以封装统一的XML解析安全配置方法,避免每次解析时重复配置,减少遗漏风险。

具体代码实现示例

DocumentBuilderFactory安全配置

DocumentBuilderFactory是Java最常用的DOM解析类,默认开启外部实体解析,需要手动关闭相关特性:

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import java.io.ByteArrayInputStream;

public class SafeXMLParser {
    public Document parseXMLSafe(String xmlContent) throws Exception {
        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);
        // 禁用XInclude处理
        dbf.setFeature("http://apache.org/xml/features/xinclude", false);
        // 忽略XML命名空间依赖
        dbf.setNamespaceAware(false);
        
        DocumentBuilder db = dbf.newDocumentBuilder();
        // 解析XML内容,这里使用字节流避免编码问题
        return db.parse(new ByteArrayInputStream(xmlContent.getBytes("UTF-8")));
    }
}

SAXParserFactory安全配置

SAX解析是事件驱动的流式解析,同样需要关闭外部实体特性:

import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import org.xml.sax.helpers.DefaultHandler;
import java.io.ByteArrayInputStream;

public class SafeSAXParser {
    public void parseXMLSafe(String xmlContent) throws Exception {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        // 禁用DTD
        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);
        // 不验证XML
        spf.setValidating(false);
        
        SAXParser parser = spf.newSAXParser();
        parser.parse(new ByteArrayInputStream(xmlContent.getBytes("UTF-8")), new DefaultHandler());
    }
}

StAX(XMLInputFactory)安全配置

StAX是流式拉取解析,配置方式如下:

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayInputStream;

public class SafeStAXParser {
    public void parseXMLSafe(String xmlContent) throws Exception {
        XMLInputFactory xif = XMLInputFactory.newInstance();
        // 禁用外部实体
        xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
        // 禁用DTD
        xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
        
        XMLStreamReader reader = xif.createXMLStreamReader(new ByteArrayInputStream(xmlContent.getBytes("UTF-8")));
        while (reader.hasNext()) {
            reader.next();
        }
        reader.close();
    }
}

第三方库的XXE防护

Jackson XML解析防护

Jackson解析XML时如果使用XmlMapper,需要关闭外部实体支持:

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;

public class SafeJacksonXML {
    public XmlMapper getSafeXmlMapper() {
        XmlMapper xmlMapper = new XmlMapper();
        // 禁用外部实体
        xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 关闭DTD支持,需要依赖jackson-dataformat-xml的版本支持,低版本可升级后使用
        // xmlMapper.getFactory().setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        return xmlMapper;
    }
}

XStream安全配置

XStream默认也支持外部实体,需要手动关闭:

import com.thoughtworks.xstream.XStream;

public class SafeXStream {
    public XStream getSafeXStream() {
        XStream xstream = new XStream();
        // 禁用DTD
        xstream.ignoreUnknownElements();
        // 关闭外部实体解析,XStream底层依赖XML解析器,可设置解析器特性
        // 建议升级到最新版本,新版本默认关闭了外部实体
        return xstream;
    }
}

防护注意事项

  • 所有接收外部XML输入的场景都需要做安全配置,不能只处理部分接口
  • 尽量使用白名单方式限制XML解析的允许内容,不要只依赖黑名单过滤
  • 定期升级XML解析相关依赖库,修复已知的安全漏洞
  • 对上传的XML文件做格式校验,拒绝不符合预期的XML结构
  • 测试阶段可以使用恶意XXE payload验证防护是否生效,比如构造读取本地文件的XML进行测试

JavaXXEXML外部实体注入安全编程修改时间:2026-06-13 02:39:26

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。