使用SchemaFactory结合XSD验证XML时的Sonar XXE漏洞告警及属性识别异常问题求助
解决XML SchemaFactory属性不识别的XXE防护问题
这个问题我之前碰到过,主要是因为你用的XML解析器实现或者JDK版本不支持JAXP 1.5新增的安全属性,咱们一步步来排查解决:
问题根源
XMLConstants.ACCESS_EXTERNAL_DTD和XMLConstants.ACCESS_EXTERNAL_SCHEMA这两个属性是JAXP 1.5规范里才新增的,对应的JDK版本要求是JDK 7 Update 40及以上,或者JDK 8+。如果你的项目用的是更早的JDK版本,或者使用了不支持JAXP 1.5的第三方XML解析器(比如旧版Apache Xerces),就会抛出这个“属性不被识别”的错误。
具体解决方案
方案1:直接升级JDK版本
这是最省心的办法,把JDK升级到7u40以上或者8及更高版本。升级后,JDK内置的SchemaFactory会原生支持这两个安全属性,你原来的代码不用修改就能正常运行。
方案2:兼容旧环境的替代配置
如果暂时没法升级JDK,或者用的是老版本第三方解析器,咱们可以换个思路,通过设置SAX相关的特性来禁用XXE,同样能达到安全验证的效果。修改你的代码如下:
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); try { // 先尝试设置JAXP 1.5的属性,不支持就捕获异常降级处理 schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); } catch (IllegalArgumentException e) { logger.warn("XML安全属性不被当前解析器支持,将使用SAX特性来防护XXE"); } Schema schema = schemaFactory.newSchema(new File(getResource(schemaFile))); Validator validator = schema.newValidator(); // 核心XXE防护配置:禁用DOCTYPE声明、外部实体加载 validator.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); validator.setFeature("http://xml.org/sax/features/external-general-entities", false); validator.setFeature("http://xml.org/sax/features/external-parameter-entities", false); validator.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); try { validator.validate(new StreamSource(new File(getResource(xmlFile)))); return true; } catch (SAXException | IOException e) { xsdInvalidData.add(xmlFile + "=" + e.getMessage()); logger.error(xmlFile + " 不符合XSD规范,进入异常处理:" + e.getMessage()); return false; }
方案3:指定支持JAXP 1.5的解析器实现
如果你的项目依赖了第三方XML解析器(比如Apache Xerces),要确保使用的是2.11.0及以上版本,这个版本开始支持JAXP 1.5的安全属性。你可以显式指定解析器类来创建SchemaFactory:
SchemaFactory schemaFactory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI, "org.apache.xerces.jaxp.validation.XMLSchemaFactory", Thread.currentThread().getContextClassLoader() ); // 之后再设置那两个属性就不会报错了 schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
内容的提问来源于stack exchange,提问作者Mahi Mokhashi
相关产品推荐
相关产品推荐

