Xml外部實體注入漏洞(XXE)與防護
阿新 • • 發佈:2019-02-13
Xml外部實體注入(XXE)
除了json外,xml也是一種常用的資料傳輸格式。對xml的解析有以下幾種常用的方式:DOM,SAX,JDOM,DOM4J,StAX等。然而這幾種解析方式都可能會出現外部實體注入漏洞,如微信支付的回撥就出現過(見參考資料2)。
XML文件結構包括xml宣告,DTD文件型別定義(可選)和文件元素,如下圖所示:
DTD的作用是定義XML文件的合法構建模組,可以在XML文件內宣告,也可以外部引用。當DTD引用外部實體,而外部實體中含有惡意程式碼時,就可能會在解析xml時執行外部實體中的惡意程式碼。這就是xml外部實體注入。
舉個簡單的栗子如下圖所示:
這裡通過引用外部實體,讀取了/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),裡面寫得很詳細,這裡就不復制了。