CVE-2020-14756 漏洞利用以及分析
0x01利用思路
weblogic的T3協議反序列化漏洞一直是一個比較熱門也比較好用的漏洞,weblogic針對該漏洞的解決方案就是不斷填充黑名單,在高版本jdk下配合jep290機制實現黑名單,在低版本下配合resolveClass進行防御,所以安全人員對于T3反序列化的利用也是一直在尋找黑名單之外的利用鏈。
CVE-2020-14756 這個漏洞的利用比較巧妙,通過利用weblogic coherence組件中的類,繞過了黑名單機制的檢測,重新能夠利用黑名單中的類,造成代碼執行。
0x02漏洞分析
在weblogic的coherence.jar中,存在著一個比較特殊的接口com.tangosol.io.ExternalizableLite,他繼承了Serializable接口。
readExternal和writeExternal方法
而ExternalizableLite接口的對象可以在com.tangosol.util.ExternalizableHelper里被序列化。
這里的nType是在writeObject寫入的,是可控的
readExternalizableLite方法的具體內容為:
這里會加載傳入的對象,對象需要是ExternalizableLite的實現類
這里直接調用class.forName還原對象
之后,會繼續調用對象的readExternal方法,這樣一來,后續的流程就繞過了ObjectInputStream對于對象的還原,而weblogic的黑名單檢測也主要是針對ObjectInputStream的,所以,現在只需要找到后續的利用鏈就可以造成代碼執行。
漏洞發現者使用了com.tangosol.util.aggregator.TopNAggregator.PartialResult這個類。這里會利用ExternalizableHelper還原m_comparator參數,是一個Comparator類型的對象。
然后調用了instantiateInternalMap方法,傳入m_comparator
首先實例化SortedBag.WrapperComparator,賦值f_comparator,然后返回TreeMap對象
接著,調用add方法,在add方法里調用super.add,即SortedBag.add,繼續調用put方法。

在put方法里,調用了compare方法
而這里又會調用WrapperComparator的compare方法

這個f_comparator就是之前已經賦值過的。
所以,最終的利用就在f_comparator這里,f_comparator從前面可以知道,需要是一個Comparator類型,這里使用的是 MvelExtractor 這是之前黑名單里的一個類,在CVE-2020-2555中有使用,不過現在我們不受黑名單的限制,MvelExtractor 沒有compare方法。于是調用父類AbstractExtractor的compare方法。
然后又會調用子類MvelExtractor的extract方法。
序列化入口一
到現在我們的入口是TopNAggregator$PartialResult,他的readExternal(DataInput in)不是標準的readExternal(ObjectInput in),序列化的過程中是不會自動調用到該方法的,所以還需要找一個入口,這里作者發現了AttributeHolder。
這里不但會將ObjectInput轉為DataInput,還會主動調用ExternalizableHelper.readObject。所以我們只需要m_oValue是TopNAggregator$PartialResult即可完成利用。
調用棧
序列化入口二
另外一個入口是com.tangosol.net.security.PermissionInfo,我們看他的readExternal方法,將輸入流傳入readCollection方法里,PermissionInfo是ExternalizableHelper的子類,所以這里PermissionInfo沒有readCollection方法,直接調用其父類ExternalizableHelper的方法。
判斷輸入流類型之后,調用了readObject。
在調用readCollection的時候,將ObjectInput轉為了DataInput
走到這里,就和之前的流程一模一樣了。
調用棧
0x03 12.1.3版本問題
經測試,12.1.3 利用存在如下問題

從前面的分析可以知道,類的加載是在loadClass方法里,利用class.forName去加載類。
這里的loader就很關鍵了,決定了哪些類可以加載,哪些類沒發加載,這里的loader是調用getContextClassLoader獲得的一個線程上下文類加載器。
這里的線程上下文類加載器是默認的 AppClassLoader,在loaders里發現JarLoader加載了的coherence組件的依賴只有coherence.jar和coherence-web.jar,而MvelExtractor在coherence-rest.jar里,所以沒有辦法加載。

以下是一些嘗試(未成功):
于是我這里先是考慮了另一個在黑名單的類,ReflectionExtractor,這個類在coherence.jar包下,不過在構造利用這個反射執行鏈的時候,需要反序列化Runtime.class對象,而Runtime.class對象不是ExternalizableLite的實現類,根據nType,在序列化的時候會調用readSerializeable方法
該方法還是會走ObjectInputStream的反序列化流程,即使是通過修改nType讓他走readExternalizable,后面還是會有類型轉換報錯。
所以這樣是不行的,12.1.3版本很多類都利用不了,比如RemoteConstructor、UniversalExtractor、LockVersionExtractor這些類在 12.1.3 版本中都沒有,已知的利用鏈在 12.1.3 來說是沒有辦法進行利用的。
0x04官方修復之梅開二度
(補丁只能針對實現了jep290的jdk)
根據補丁來看:
對輸入流的類型進行了判斷,如果是ObjectInputStream,那么會去調用checkObjectInputFilter方法,方法如下:

這里會獲取filter,在ExternalizableHelper的靜態代碼塊里初始化了filter
首先會獲取是否存在ObjectInputFilter,來判斷jdk環境中是否存在jep290。
然后通過getObjectInputFilter/getInternalObjectInputFilter方法去獲取serialFilter,之后,調用checkInput,對當前序列化的類進行檢測。
不過,對于沒有實現jep290的jdk版本而言,這個修補是沒有作用的,因為低版本jdk不存在ObjectInputFilter,所以說filter參數就為null,也就是說checkObjectInputFilter方法直接返回true。
既然為true,那么還是能進行類的實例化。
原創: ob1t0 補天平臺
原創鏈接:https://mp.weixin.qq.com/s/QT3K__1EMXC0uqB...