2016-11-17 271 views
2

我们对我们的代码进行了安全审计,他们提到我们的代码易受外部实体(XXE)攻击。如何防止XXE攻击

说明- XML外部实体攻击受益于XML特性,以便在处理时动态构建文档。 XML 实体允许从给定资源动态地包含数据。外部实体允许XML文档包含来自外部URI的数据 。除非进行了其他配置,否则外部实体会迫使XML解析器通过URI访问指定的资源 ,例如本地机器上或远程系统上的文件。此行为将应用程序暴露给XML实体(XXE)攻击,该攻击可用于执行本地系统的拒绝服务,未经授权访问本地计算机上的文件,扫描远程计算机并执行拒绝服务远程系统。 以下XML文档显示XXE攻击的示例。

<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE foo [ 
<!ELEMENT foo ANY > 
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo> 

此示例可能崩溃的服务器(在UNIX系统上),如果XML解析器尝试与的 在/ dev /随机文件的内容来替代实体。

建议- 应该安全地配置XML解组器,以便它不允许外部实体作为传入XML文档的一部分。 为了避免XXE注入,请不要使用直接将java.io.File,java.io.Reader或 java.io.InputStream处理XML源的解组方法。与安全配置的解析器解析文档并使用接受的安全

解析器作为XML源作为显示在下面的例子的解组方法:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
dbf.setExpandEntityReferences(false); 
DocumentBuilder db = dbf.newDocumentBuilder(); 
Document document = db.parse(<XML Source>); 
Model model = (Model) u.unmarshal(document); 

而编写的代码是下面其中发现XXE攻击 -

Transformer transformer = TransformerFactory.newInstance().newTransformer(); 
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
System.out.println("outputing to : " + outputLocation); 
File outputFile = new File(outputLocation); 
StreamResult result = new StreamResult(outputFile); 
DOMSource source = new DOMSource(doc); 
transformer.transform(source, result); 

请帮助我如何在我的代码中实现以上建议。

任何人都可以帮助我失去东西的地方吗?任何人帮助表示赞赏!

回答

1

您需要打开TransformerFactory上的安全处理功能。它会限制某些可能是恶意的事情发生(DOS攻击等)

TransformerFactory tf = TransformerFactory.newInstance(); 
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); 
Transformer transformer = tf.newTransformer(); 
+0

感谢您的回应,是的,但我需要在现有的逻辑中实现DocumentBuilderFactory .... btw我用你的给出的建议,但得到错误“方法setFeature(字符串,布尔)是未定义的类型变压器”。 – SANNO

+0

呃,对不起,您需要将其设置在TransformerFactory中。 – Kayaman

+0

谢谢卡亚曼!其工作正常,但你可以帮助用DocumentBuilderFactory概念取代TransformerFactory概念。真的会是可观的。 – SANNO

0

您可以使用同样的方法与DocumentBuilderFactory

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); 
... 

为了让大家自动使用这个,你需要创建自己的实现(通过扩展你正在使用的那个;使用你的调试器来查明)。在构造函数中设置该功能。

然后,您可以将新工厂传递给Java虚拟机的系统属性javax.xml.parsers.DocumentBuilderFactory,并且每个人都将使用它。