如何防止XXE攻击



我们对我们的代码进行了安全审计,它提到我们的代码容易受到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.Filejava.io.Readerjava.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();

最新更新