如何防止XXE攻击
我们对代码进行了安全审核,其中提到我们的代码容易受到 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 源直接处理为 、 或 的 unmarshal 方法。使用安全配置的解析器分析文档,并使用将安全解析器作为 XML 源的非元化方法,如以下示例所示:
java.io.File
java.io.Reader
java.io.InputStream
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);
如何在我的代码中实现上述建议?我在哪里错过了什么?