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平臺進行回顯。