1. 程式人生 > >Java 審計之XXE篇

Java 審計之XXE篇

# Java 審計之XXE篇 ## 0x00 前言 在以前XXE漏洞瞭解得並不多,只是有一個初步的認識和靶機裡面遇到過。下面來 深入瞭解一下該漏洞的產生和利用。 ## 0x01 XXE漏洞 當程式在解析XML輸入時,允許引用外部實體,導致能夠引用一個外部惡意檔案,可導致執行系統命令,內網埠檢測,檔案讀取,攻擊內網服務,dos攻擊等。 在解析外部實體的過程中,XML解析器可以根據URL中指定的方案(協議)來查詢各種網路協議和服務(DNS,FTP,HTTP,SMB等)。 外部實體對於在文件中建立動態引用非常有用,這樣對引用資源所做的任何更改都會在文件中自動更新。 但是,在處理外部實體時,可以針對應用程式啟動許多攻擊。 這些攻擊包括洩露本地系統檔案,這些檔案可能包含密碼和私人使用者資料等敏感資料,或利用各種方案的網路訪問功能來操縱內部應用程式。 通過將這些攻擊與其他實現缺陷相結合,這些攻擊的範圍可以擴充套件到客戶端記憶體損壞,任意程式碼執行,甚至服務中斷,具體取決於這些攻擊的上下文。 具體利用方式參考: [一篇文章帶你深入理解漏洞之 XXE 漏洞](https://xz.aliyun.com/t/3357) ## 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平臺進行