Java 8中TransformerFactory防XXE/XSLT攻击属性不存在问题求助
解决Java 8中TransformerFactory设置安全属性报错的问题
问题原因
Java 8自带的默认TransformerFactory实现(通常是Xalan)不支持XMLConstants.ACCESS_EXTERNAL_DTD和XMLConstants.ACCESS_EXTERNAL_STYLESHEET这两个属性——它们是JAXP 1.5规范新增的,早期版本的Xalan未实现这些属性,因此调用setAttribute时会抛出"属性不存在"的异常。
解决方案
方案1:切换到支持安全属性的TransformerFactory实现
使用Apache Xalan 2.7.2及以上版本,或Saxon这类支持JAXP安全属性的XSLT处理器。
- 若用Maven,添加依赖:
<!-- Apache Xalan 新版本 --> <dependency> <groupId>xalan</groupId> <artifactId>xalan</artifactId> <version>2.7.2</version> </dependency>
- 代码中指定使用该实现:
TransformerFactory transformerFactory = TransformerFactory.newInstance( "org.apache.xalan.processor.TransformerFactoryImpl", Thread.currentThread().getContextClassLoader() ); transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
方案2:通过系统属性配置安全限制
无需更换TransformerFactory,在应用启动时添加JVM参数:
-Djavax.xml.accessExternalDTD= -Djavax.xml.accessExternalStylesheet= -Djavax.xml.transform.TransformerFactory=com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
或在创建TransformerFactory前,代码中设置系统属性:
System.setProperty("javax.xml.accessExternalDTD", ""); System.setProperty("javax.xml.accessExternalStylesheet", ""); TransformerFactory transformerFactory = TransformerFactory.newInstance(); transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
方案3:手动验证输入(兜底措施)
若上述方案无法实施,可在处理前手动禁用外部实体解析,避免攻击:
// 解析XML时禁用外部实体 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new File("input.xml")); // 使用Transformer处理已安全解析的文档 TransformerFactory transformerFactory = TransformerFactory.newInstance(); transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); Transformer transformer = transformerFactory.newTransformer(new StreamSource("stylesheet.xsl")); transformer.transform(new DOMSource(doc), new StreamResult(new File("output.xml")));
内容的提问来源于stack exchange,提问作者Pablo
相关产品推荐
相关产品推荐

