Java怎么安全地处理外部实体 防止XXE

13次阅读

java防XXE攻击需禁用外部实体和DTD解析:对DocumentBuilder、SAXParser、transformer等均须显式关闭相关特性;推荐Jackson xml或DOM4J并配合白名单EntityResolver、输入校验与WAF防护。

Java怎么安全地处理外部实体 防止XXE

Java中防止XXE(XML External Entity)攻击,核心是禁用外部实体解析和DTD处理。默认的xml解析器(如JAXP中的DocumentBuilder、SAXParser、Transformer)若未显式配置,可能启用外部实体,导致敏感文件读取、SSRF甚至远程代码执行。

禁用外部实体和DTD解析

对所有XML解析器实例,必须显式关闭http://apache.org/xml/features/disallow-doctype-declhttp://xml.org/sax/features/external-general-entities等关键特性:

  • DocumentBuilder:设置setFeature("http://apache.org/xml/features/disallow-doctype-decl", true),再设setFeature("http://xml.org/sax/features/external-general-entities", false)
  • SAXParser:在SAXParserFactory上调用setFeature(),同样禁用上述两项,以及http://xml.org/sax/features/external-parameter-entities
  • Transformer(用于XSLT):通过TransformerFactory设置FEATURE_SECURE_PROCESSINGtrue,并禁用http://javax.xml.XMLConstants/feature/secure-processing

使用白名单机制替代通用解析

如果业务必须处理带DOCTYPE的XML(极少见),不要开放全部实体,而是采用白名单方式预定义允许的实体,并重写EntityResolver

  • 实现org.xml.sax.EntityResolver,对resolveEntity方法只返回已知安全的InputSource
  • 拒绝所有systemIdfile://http://https://jar:的请求
  • 避免调用new InputSource(new FileInputstream(...))等直接加载路径的操作

优先选用现代、安全默认的库

避免依赖老版本JDK或未加固的第三方XML工具

立即学习Java免费学习笔记(深入)”;

  • JAXB(Unmarshaller)需配合SecurityManager或显式禁用外部实体;JDK 17+已弃用,建议迁移到Jackson XML或DOM4J(配置后)
  • 推荐Jackson XML(jackson-dataformat-xml):默认不解析DTD,且可通过XmlFactory关闭XMLStreamConstants.FEATURE_DOCTYPE_DECLARATION
  • DOM4J 2.1.4+ 默认禁用外部实体,但仍建议调用DocumentHelper.parseText(xml).setEntityResolver(NULL)并校验输入

补充防御:输入验证与运行时限制

解析前加一层过滤,能显著降低风险:

  • 用正则或XML Schema(XSD)预校验XML结构,拒绝含/code>、的输入
  • 在容器或jvm层启用SecurityManager(虽已废弃,但在受限环境仍可限制FilePermission
  • 生产环境部署WAF规则,拦截常见XXE载荷如]]>

基本上就这些。关键不是“怎么解析XML”,而是“怎么确保它不会去碰不该碰的东西”。每种解析器都得单独配,不能只改一处就以为全安全了。

text=ZqhQzanResources