如何防止XXE攻击

SAN*_*NNO 15 java xml transform xml-parsing

我们对代码进行了安全审核,并提到我们的代码容易受到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>
Run Code Online (Sandbox Code Playgroud)

如果XML解析器尝试使用/ dev/random文件的内容替换实体,则此示例可能会使服务器(在UNIX系统上)崩溃.

建议

应该安全地配置XML unmarshaller,以便它不允许外部实体作为传入XML文档的一部分.

要避免XXE注入,请不要使用直接处理XML源的unmarshal方法java.io.File,java.io.Readerjava.io.InputStream.使用安全配置的解析器解析文档,并使用将安全解析器作为XML源的unmarshal方法,如以下示例所示:

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

下面的代码是审计发现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);
Run Code Online (Sandbox Code Playgroud)

如何在我的代码中实现上述建议?我在哪里错过了什么?

Aar*_*lla 15

您可以将相同的方法用于DocumentBuilderFactory

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
...
Run Code Online (Sandbox Code Playgroud)

为了使每个人都自动使用此功能,您需要创建自己的实现(通过扩展当前使用的实现;使用调试器进行查找)。在构造函数中设置功能。

然后,您可以将要在System属性中使用的新工厂传递javax.xml.parsers.DocumentBuilderFactory给Java VM,每个人都将使用它。


bea*_*eat 6

请注意,仅使用FEATURE_SECURE_PROCESSING似乎不够安全(来自blackhat-pdf):

...尽管Oracle提出了建议,但启用FEATURE _SECURE_PROCESSING时,XML解析器实际上并不限制外部连接。

OWASP建议使用ACCESS_EXTERNAL_DTD和ACCESS_EXTERNAL_STYLESHEET。

这将使:

TransformerFactory trfactory = TransformerFactory.newInstance();
trfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Run Code Online (Sandbox Code Playgroud)

实际上,这个问题是以下内容的重复:如何防止在TransformerFactory上进行XML外部实体注入


Kay*_*man 2

您需要打开TransformerFactory. 它将限制某些可能恶意的事情的发生(DOS 攻击等)

TransformerFactory tf = TransformerFactory.newInstance();
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer transformer = tf.newTransformer();
Run Code Online (Sandbox Code Playgroud)