Java 審計之XXE篇
0x00 前言
在以前XXE漏洞了解得並不多,只是有一個初步的認識和靶機里面遇到過。下面來 深入了解一下該漏洞的產生和利用。
0x01 XXE漏洞
當程序在解析XML輸入時,允許引用外部實體,導致能夠引用一個外部惡意文件,可導致執行系統命令,內網端口檢測,文件讀取,攻擊內網服務,dos攻擊等。
在解析外部實體的過程中,XML解析器可以根據URL中指定的方案(協議)來查詢各種網絡協議和服務(DNS,FTP,HTTP,SMB等)。 外部實體對於在文檔中創建動態引用非常有用,這樣對引用資源所做的任何更改都會在文檔中自動更新。 但是,在處理外部實體時,可以針對應用程序啟動許多攻擊。 這些攻擊包括泄露本地系統文件,這些文件可能包含密碼和私人用戶數據等敏感數據,或利用各種方案的網絡訪問功能來操縱內部應用程序。 通過將這些攻擊與其他實現缺陷相結合,這些攻擊的范圍可以擴展到客戶端內存損壞,任意代碼執行,甚至服務中斷,具體取決於這些攻擊的上下文。
具體利用方式參考: 一篇文章帶你深入理解漏洞之 XXE 漏洞
0x02 Java中XXE的產生
其實說白了,也還是在web應用中接受並且解析xml的時候允許引用外部的實體。web應用中需要解析的xml,需要是可控的。
那么先來看看漏洞產生的代碼,前面本來想着是自己去寫一個XXE的漏洞代碼,但是發現寫的時候報各種錯,參考其他文章的代碼,調試半天還是報錯。所以這里就借用JoyChou師傅開源的Java Sec Code項目上來做一個演示。
項目地址:https://github.com/JoyChou93/java-sec-code/
DocumentBuilder
DocumentBuilder類是JDK自帶的類,在該類解析產生的XXE漏洞是有回顯的。
public String DocumentBuilderVuln01(HttpServletRequest request) {
try {
String body = WebUtils.getRequestBody(request);
logger.info(body);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
StringReader sr = new StringReader(body);
InputSource is = new InputSource(sr);
Document document = db.parse(is); // parse xml
// 遍歷xml節點name和value
StringBuilder buf = new StringBuilder();
NodeList rootNodeList = document.getChildNodes();
for (int i = 0; i < rootNodeList.getLength(); i++) {
Node rootNode = rootNodeList.item(i);
NodeList child = rootNode.getChildNodes();
for (int j = 0; j < child.getLength(); j++) {
Node node = child.item(j);
buf.append(String.format("%s: %s\n", node.getNodeName(), node.getTextContent()));
}
}
sr.close();
return buf.toString();
} catch (Exception e) {
logger.error(e.toString());
return EXCEPT;
}
saxReader
saxReader是第三方的庫,該類是無回顯的
public String SAXReaderVuln(HttpServletRequest request) {
try {
String body = WebUtils.getRequestBody(request);
logger.info(body);
SAXReader reader = new SAXReader();
// org.dom4j.Document document
reader.read(new InputSource(new StringReader(body))); // cause xxe
} catch (Exception e) {
logger.error(e.toString());
return EXCEPT;
}
SAXBuilder
第三方庫
public String SAXBuilderVuln(HttpServletRequest request) {
try {
String body = WebUtils.getRequestBody(request);
logger.info(body);
SAXBuilder builder = new SAXBuilder();
// org.jdom2.Document document
builder.build(new InputSource(new StringReader(body))); // cause xxe
return "SAXBuilder xxe vuln code";
} catch (Exception e) {
logger.error(e.toString());
return EXCEPT;
SAXParserFactory
該類也是JDK內置的類,但他不可回顯內容,可借助dnslog平台
public String SAXParserVuln(HttpServletRequest request) {
try {
String body = WebUtils.getRequestBody(request);
logger.info(body);
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
parser.parse(new InputSource(new StringReader(body)), new DefaultHandler()); // parse xml
return "SAXParser xxe vuln code";
} catch (Exception e) {
logger.error(e.toString());
return EXCEPT;
}
}
XMLReaderFactory
public String xmlReaderVuln(HttpServletRequest request) {
try {
String body = WebUtils.getRequestBody(request);
logger.info(body);
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
xmlReader.parse(new InputSource(new StringReader(body))); // parse xml
return "xmlReader xxe vuln code";
} catch (Exception e) {
logger.error(e.toString());
return EXCEPT;
}
Digester
public String DigesterVuln(HttpServletRequest request) {
try {
String body = WebUtils.getRequestBody(request);
logger.info(body);
Digester digester = new Digester();
digester.parse(new StringReader(body)); // parse xml
} catch (Exception e) {
logger.error(e.toString());
return EXCEPT;
}
return "Digester xxe vuln code";
XMLReader
public String XMLReaderVuln(HttpServletRequest request) {
try {
String body = WebUtils.getRequestBody(request);
logger.info(body);
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.parse(new InputSource(new StringReader(body)));
} catch (Exception e) {
logger.error(e.toString());
return EXCEPT;
}
return "XMLReader xxe vuln code";
}
修復方法
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
0x03 結尾
本文作為一個記錄文,在Java中能解析XXE的類會比較多。因為在Java中配置文件會頻繁的使用到XML文件或是數據傳輸。導致XXE漏洞可能會比其他語言的出現頻率高(瞎說的)。在審計的時候可以這么查看有沒有使用到那幾個set方法被修復掉,如果沒有那么就可以存在XXE。當然也要查看使用的是哪個類進行解析,有沒有回顯的情況。有回顯的話,能不能出網,能出網的話就可以借助dnslog平台進行回顯。