我们对我们的代码进行了安全审计,它提到我们的代码容易受到XML EXternal Entity(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 文件。
建议
应安全地配置 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);
如何在代码中实现上述建议?我哪里错过了东西?
您可以对DocumentBuilderFactory
使用相同的方法:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
...
为了让每个人都自动使用它,你需要创建自己的实现(通过扩展你当前使用的实现;使用调试器找出答案(。在构造函数中设置功能。
然后,可以将要在 System 属性javax.xml.parsers.DocumentBuilderFactory
中使用的新工厂传递给 Java VM,每个人都会使用它。
,单独使用FEATURE_SECURE_PROCESSING似乎不够安全(来自blackhat-pdf(:
。尽管甲骨文推荐了 XML 解析器实际上不会限制外部连接,在以下情况下 特征 _SECURE_PROCESSING 已启用。
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, "");
实际上这个问题是重复的:如何防止变压器工厂上的XML外部实体注入
由于市场上有大量的xml解析引擎,因此防止XXE攻击的方法因引擎而异。 请参考您的引擎文档。这里的基金会是为了防止外部 DOCTYPE 声明。如果需要外部 DOCTYPE 声明,则禁用外部通用实体和外部参数实体将防止对代码的 XXE 攻击。下面是在使用 SAX 分析器时防止 XXE 的示例代码。
public class MyDocumentBuilderFactory {
public static DocumentBuilderFactory newDocumentBuilderFactory() {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
try {
documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities",false);
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities",false)
} catch(ParserConfigurationException exp){
exp.printStackTrace();
}
return documentBuilderFactory;
}
}
在TransformerFactory
上打开安全处理功能。它将限制某些可能的恶意事情发生(DOS攻击等(。
TransformerFactory tf = TransformerFactory.newInstance();
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer transformer = tf.newTransformer();