Xml外部实体注入漏洞(XXE)与防护

Xml外部实体注入(XXE)

除了json外,xml也是一种常用的数据传输格式。对xml的解析有以下几种常用的方式:DOM,SAX,JDOM,DOM4J,StAX等。然而这几种解析方式都可能会出现外部实体注入漏洞,如微信支付的回调就出现过(见参考资料2)。

XML文档结构包括xml声明,DTD文档类型定义(可选)和文档元素,如下图所示:
Xml外部实体注入漏洞(XXE)与防护_第1张图片

DTD的作用是定义XML文档的合法构建模块,可以在XML文档内声明,也可以外部引用。当DTD引用外部实体,而外部实体中含有恶意代码时,就可能会在解析xml时执行外部实体中的恶意代码。这就是xml外部实体注入。

举个简单的栗子如下图所示:
Xml外部实体注入漏洞(XXE)与防护_第2张图片

这里通过引用外部实体,读取了/etc/passwd。详细的例子见参考资料1。

XXE防护

DOM解析防护(JAXP DocumentBuilderFactory, SAXParserFactory and DOM4J)

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; // catching unsupported features
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
String FEATURE = null;
try {
    // 首要选择。不允许DTDs,几乎可以阻止所有的XML实体攻击
    FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
    dbf.setFeature(FEATURE, true);
} catch (ParserConfigurationException e) {
    // This should catch a failed setFeature feature
    logger.info("ParserConfigurationException was thrown. The feature '" +
    FEATURE + "' is probably not supported by your XML processor.");
} catch (SAXException e) {
    // On Apache, this should be thrown when disallowing DOCTYPE
    logger.warning("A DOCTYPE was passed into the XML document");
} catch (IOException e) {
    // XXE that points to a file that doesn't exist
    logger.error("IOException occurred, XXE may still possible: " + e.getMessage());
}
DocumentBuilder safebuilder = dbf.newDocumentBuilder();

如果不能完全禁用DTDs,那么至少使用以下方案:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
String FEATURE = null;
try {
    // If you can't completely disable DTDs, then at least do the following:
    // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
    // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
    // JDK7+ - http://xml.org/sax/features/external-general-entities 
    FEATURE = "http://xml.org/sax/features/external-general-entities";
    dbf.setFeature(FEATURE, false);

    // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
    // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
    // JDK7+ - http://xml.org/sax/features/external-parameter-entities 
    FEATURE = "http://xml.org/sax/features/external-parameter-entities";
    dbf.setFeature(FEATURE, false);

    // Disable external DTDs as well
    FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
    dbf.setFeature(FEATURE, false);

    // 此处依据为Timothy Morgan's 2014的论文: "XML Schema, DTD, and Entity Attacks"
    dbf.setXIncludeAware(false);
    dbf.setExpandEntityReferences(false);

    // 以下注意点同样出自Timothy Morgan's的论文
    // If for some reason support for inline DOCTYPEs are a requirement, then 
    // ensure the entity settings are disabled (as shown above) and beware that SSRF attacks
    // (http://cwe.mitre.org/data/definitions/918.html) and denial 
    // of service attacks (such as billion laughs or decompression bombs via "jar:") are a risk."

    // remaining parser logic
} catch (ParserConfigurationException e) {
    // This should catch a failed setFeature feature
    logger.info("ParserConfigurationException was thrown. The feature '" +
    FEATURE + "' is probably not supported by your XML processor.");
} catch (SAXException e) {
    // On Apache, this should be thrown when disallowing DOCTYPE
    logger.warning("A DOCTYPE was passed into the XML document");
} catch (IOException e) {
    // XXE that points to a file that doesn't exist
    logger.error("IOException occurred, XXE may still possible: " + e.getMessage());
}
DocumentBuilder safebuilder = dbf.newDocumentBuilder();

其他解析方式的xxe防护见官方文档(参考资料3),里面写得很详细,这里就不复制了。

参考资料:

  1. https://www.cnblogs.com/miyeah/p/4526088.html。
  2. https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=23_5
  3. https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXTransformerFactory

你可能感兴趣的:(数据安全,网络编程,Java基础)