我们对我们的代码进行了安全审计,它提到我们的代码容易受到 XML 外部实体 (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> > > ``` > > 如果 XML 解析器试图用 /dev/random 文件的内容替换实体,则此示例可能会使服务器(在 UNIX 系统上)崩溃。 > > ## 推荐 > > 应该安全地配置 XML 解组器,以便它不允许外部实体作为传入 XML 文档的一部分。 > > 为避免 XXE 注入,请勿使用直接将 XML 源处理为 `java.io.File` , `java.io.Reader` 或 `java.io.InputStream` 使用安全配置的解析器解析文档,并使用将安全解析器作为 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);
”`
如何在我的代码中实施上述建议?我在哪里遗漏了东西?
原文由 SANNO 发布,翻译遵循 CC BY-SA 4.0 许可协议
您可以对
DocumentBuilderFactory
使用相同的方法:为了让每个人都自动使用它,您需要创建自己的实现(通过扩展您当前正在使用的实现;使用调试器找出答案)。在构造函数中设置功能。
然后你可以将系统属性中使用的新工厂
javax.xml.parsers.DocumentBuilderFactory
传递给Java VM,每个人都会使用它。