作者:kejaly@白帽匯安全研究院
校對:r4v3zn@白帽匯安全研究院

前言

Coherence 組件是 WebLogic 中的一個核心組件,內置在 WebLogic 中。關于 Coherence 組件的官方介紹:https://www.oracle.com/cn/java/coherence/

https://images.seebug.org/content/images/2021/08/11/1628653081000-image-20210802113229602.png-w331s

近些年,weblogic Coherence 組件反序列化漏洞被頻繁爆出,苦于網上沒有公開對 weblogic Coherence 組件歷史反序列化漏洞的總結,導致很多想入門或者了解 weblogic Coherence 組件反序列化漏洞的朋友不知道該怎么下手,于是本文便對 weblogic Coherence 組件歷史反序列化漏洞做出了一個總結和分析。

關于 Coherence 組件反序列化漏洞利用鏈的架構,我把他分為兩個,一個是基于 ValueExtractor.extract 的利用鏈架構,另一個則是基于 ExternalizableHelper 的利用鏈架構。

前置知識

想理清 WebLogic 的 Coherence 組件歷史反序列化漏洞需要首先了解一些 Coherence 組件反序列化漏洞中經常會涉及的一些接口和類。他們在 Coherence 組件反序列化漏洞利用中經常出現。

ValueExtractor

com.tangosol.util.ValueExtrator 是一個接口: https://images.seebug.org/content/images/2021/08/11/1628653081000-image-20210725145241910.png-w331s

在 Coherence 中 很多名字以 Extrator 結尾的類都實現了這個接口: https://images.seebug.org/content/images/2021/08/11/1628653081000-image-20210725145311604.png-w331s

這個接口中聲明了一個 extract 方法,而 ValueExtractor.extract 正是 Coherence 組件歷史漏洞( ValueExtractor.extract 鏈部分 )的關鍵。

ExternalizableLite

Coherence 組件中存在一個 com.tangosol.io.ExternalizableLite,它繼承了 java.io.Serializable,另外聲明了 readExternalwriteExternal 這兩個方法。 https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210728101447302.png-w331s

com.tangosol.io.ExternalizableLite 接口 和 jdk 原生的 java.io.Externalizable 很像,注意不要搞混了。

ExternalizableHelper

上面提到的 com.tangosol.io.ExternalizableLite 接口的實現類的序列化和反序列化操作,都是通過 ExternalizableHelper 這個類來完成的。

我們可以具體看 ExternalizableHelper 這個類是怎么對實現 com.tangosol.io.ExternalizableLite 接口的類進行序列化和反序列化的,這里以 readObject 方法為例,writeObject 讀者可自行去查看:

https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210728102323560.png-w331s

如果傳入的DataInput 不是 PofInputStream 的話(Coherence 組件歷史漏洞 涉及到的 ExternalizableHelper.readObject 傳入的 DataInput 都不是 PofInputStream),ExternalizableHelper#readObject 中會調用 ExternalizableHelper#readObjectInternal 方法:

readObjectInternal 中會根據傳入的中 nType 進行判斷,進入不同的分支: https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210728103543135.png-w331s

對于實現 com.tangosol.io.ExternalizableLite 接口的對象,會進入到 readExternalizableLite 方法:

https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210728104059476.png-w331s

可以看到在 readExternalizableLite 中 1125 行會根據類名加載類,然后并且實例化出這個類的對象,然后調用它的 readExternal() 方法。

漏洞鏈

ValueExtractor.extract

我們在分析反序列化利用鏈的時候,可以把鏈分為四部分,一個是鏈頭,一個是危險的中間的節點(漏洞點),另一個是調用危險中間節點的地方(觸發點),最后一個則是利用這個節點去造成危害的鏈尾。

在 Coherence 組件 ValueExtractor.extract 利用鏈架構中,這個危險的中間節點就是 ValueExtractor.extract 方法。

漏洞點

ReflectionExtractor

ReflectionExtractor 中的 extract 方法含有對任意對象方法的反射調用: https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210725151740093.png-w331s

配合 ChainedExtractorConstantExtractor 可以實現類似 cc1 中的 transform 鏈的調用。

涉及 CVE

CVE-2020-2555,CVE-2020-2883

MvelExtractor

MvelExtrator 中的 extract 方法,會執行任意一個 MVEL 表達式(RCE): https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210725151958385.png-w331s

而在序列化和反序列化的時候 m_sExpr 會參與序列化和反序列化: https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210725152123268-16274409140731.png-w331s

所以 m_xExpr 可控,所以就導致可以利用 MvelExtrator.extrator 來達到執行任意命令的作用。

涉及 CVE

CVE-2020-2883

UniversalExtractor

UniversalExtractor(Weblogic 12.2.1.4.0 獨有) 中的 extract 方法,可以調用任意類中的的 getis 開頭的無參方法,可以配合 jdbsRowset,利用 JDNI 來遠程加載惡意類實現 RCE。

具體細節可以參考:https://nosec.org/home/detail/4524.html

涉及 CVE

CVE-2020-14645,CVE-2020-14825 , CVE-2020-14841

LockVersionExtractor

oracle.eclipselink.coherence.integrated.internal.cache.LockVersionExtractor 中的 extract() 方法,可以調用任意 AttributeAccessorgetAttributeValueFromObject 方法,賦值 AccessorMethodAttributeAccessor 進而可以實現調用任意類的無參方法。 https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210730155536540.png-w331s

https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210730160730854.png-w331s

具體細節可參考:https://cloud.tencent.com/developer/article/1740557

MethodAttributeAccessor.getAttributeValueFromObject,本質是利用MethodAttributeAccessor.getAttributeValueFromObject中存在任意無參方法調用,在 CVE-2021-2394 中也利用到了。 https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210730155032451.png-w331s

涉及 CVE

CVE-2020-14825 , CVE-2020-14841

FilterExtractor.extract

filterExtractor.extract 中存在任意 AttributeAccessor.getAttributeValueFromObject(obj) 的調用,賦值 this.attributeAccessor 為上面說的MethodAttributeAccessor 就可以導致任意無參方法的調用。 https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210730155415313.png-w331s

https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210730155505477.png-w331s

關于 readAttributeAccessor 的細節可以看 CVE-2021-2394:https://blog.riskivy.com/weblogic-cve-2021-2394-rce%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/ https://www.cnblogs.com/potatsoSec/p/15062094.html

涉及 CVE

CVE-2021-2394

觸發點

上面例舉出了很多危險的 ValueExtractor.extract 方法,接下來再看看哪里存在調用 ValueExtractor.extract 方法的地方。

Limitfiler

Limitfiler 中 Limitfiler.toString 中存在任意 ValueExtractor.extract 方法調用: https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210728114626359.png-w331s

由于 this.m_comparator 參與序列化和反序列化,所以可控: https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210728114758555.png-w331s

我們只需要賦值 this.m_comparator 為 惡意的 ValueExtractor 就可以實現任意 ValueExtractor .extract 方法的調用。toString 方法,則可以利用 CC5 中用到的 BadAttributeValueExpException 來觸發。

涉及 CVE

CVE-2020-2555

ExtractorComparator

ExtractorComparator.compare ,其實是針對 CVE-2020-2555 補丁的繞過,CVE-2020-2555 的修復方法中修改了 Limitfiler.toString 方法,也就是說修改了一個調用 ValueExtractor.extract 方法的地方。 而 CVE-2020-2883 則找到另一個調用 ValueExtractor.extract 的地方,也就是 ExtractorComparator.compare

ExtratorComparator.compare 中存在任意(因為 this.m_extractor 參與序列化和反序列化) ValueExtractorextract 方法調用。 https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210728115727611.png-w331s

https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210728115739991.png-w331s

Comparator.compare 方法,則可以通過 CC2 中用到的PriorityQueue.readObject` 來觸發。

另外在 weblogic 中, BadAttributeValueExpException.readObject 中也可以實現調用任意 compartor.compare方法: https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210728120040372.png-w331s

涉及 CVE

CVE-2020-2883,修復方法是將 ReflectionExtractorMvelExtractor 加入了黑名單 。

CVE-2020-14645 使用 com.tangosol.util.extractor.UniversalExtractor 繞過,修復方法將 UniversalExtractor 加入黑名單。

CVE-2020-14825,CVE-2020-14841 使用 oracle.eclipselink.coherence.integrated.internal.cache.LockVersionExtractor.LockVersionExtractor 進行繞過。

ExternalizableHelper

在分析ExternalizableHelper 利用鏈架構的時候,我們依然可以把鏈分為四部分,一個是鏈頭,一個是危險的中間的節點(漏洞點),另一個是調用危險中間節點的地方(觸發點),最后一個則是利用這個節點去造成危害的鏈尾。

ExternalizableHelper 利用鏈架構中,這個危險的中間節點就是 ExternalizableLite.readExternal 方法。

weblogic 對于反序列化類的過濾都是在加載類時進行的,因此在 ExternalizableHelper.readExternalizableLite 中加載的 class 是不受黑名單限制的。 https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210730135848902.png-w331s

具體原因是:weblogic 黑名單是基于 jep 290 ,jep 290 是在 readObject 的時候,在得到類名后去檢查要反序列化的類是否是黑名單中的類。而這里直接使用的 loadClass 去加載類,所以這里不受 weblogic 黑名單限制。(也可以這么理解: jep 290 是針對在反序列化的時候,通過對要加載類進行黑名單檢查。而這里直接通過 loadClass 加載,并沒有通過反序列化,和反序列化是兩碼事,當然在后續 readExternal 的時候還是受 weblogic 黑名單限制,因為走的是反序列化那一套)

weblogic 黑名單機制可以參考:https://cert.#/report/detail?id=c8eed4b36fe8b19c585a1817b5f10b9ehttps://cert.#/report/detail?id=0de94a3cd4c71debe397e2c1a036436fhttps://www.freebuf.com/vuls/270372.html

漏洞點

PartialResult

https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210806191659163.png-w331s

com.tangosol.util.aggregator.TopNAggregator.PartialResultreadExternal 會觸發任意 compartor.compare 方法。

大致原理:

在 149 行會把comparator 作為參數傳入 TreeMap 的構造函數中。

然后 153 行,會調用 this.add ,this.add 會調用 this.m_map.put 方法,也就是說調用了 TreeMap 的 put 方法,這就導致了 comparator.compare()的調用。

具體分析見:https://mp.weixin.qq.com/s/E-4wjbKD-iSi0CEMegVmZQ

然后調用 comparator.compare 就可以接到 ExtractorComparator.compare 那里去了,從而實現 rce 。

涉及 CVE
CVE-2020-14756 (1月)

ExternalizableHelper 的利用第一次出現是在 CVE-2020-14756 中。利用的正是 ExternalizableHelper 的反序列化通過 loadClass 加載類,所以不受 weblogic 之前設置的黑名單的限制。具體利用可以參考:https://mp.weixin.qq.com/s/E-4wjbKD-iSi0CEMegVmZQ

CVE-2020-14756 的修復方法則是對 readExternalizable 方法傳入的 Datainput 檢查,如果是 ObjectInputStream 就調用 checkObjectInputFilter() 進行檢查,checkObjectInputFilter 具體是通過 jep290 來檢查的。 https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210730135848902.png-w331s

CVE-2021-2135 (4月)

上面補丁的修復方案 只是檢查了 DataInputObjectInputStream 的情況, 卻沒有過濾其他 DataInput 類型 。

那我們只需要找其他調用 readExternalizableit 函數的地方,并且傳入的參數不是 ObjectInputStream 就可以了。【ObjectInputStream 一般是最常見的,通常來說是 readObject =>readObjectInternal =>readExternalizableite 這種鏈,也就是上游是常見的 readObject, 所以補丁就可能只注意到ObjectInputStream 的情況。】

所以CVE-2021-2135 繞過的方法就是設置傳入 readExternalizableite 函數的參數類型為 BufferInput 來進行繞過。

ExternalizableHelper 中調用 readObjectInternal 的地方有兩處,一處是 readObjectInternal , 另一處則是 deserializeInternal 。而 deserializeInternal 會先把 DataInput 轉化為 BufferInut https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210725192343651.png-w331s

所以只要找調用 ExternalizableHelper .deserializeInternal 的地方。

ExternalizableHelper.fromBinary (和 ExternalizableHelper.readObject 平級的關系 )里就調用了 deserializeInternal , 所以只需要找到一個地方用 來 ExternalizableHelper.fromBinary 來反序列化就可以接上后面的(CVE-2020-14756)利用鏈了。

然后就是找 調用了 ExternalizableHelper.fromBinary 的方法的地方。SimpleBinaryEntry 中的 getKeygetValue方法中存在 ExternalizableHelper.fromBinary 的調用,所以就只要找到調用 getKeygetValue 的地方就可以了。 https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210806191959478.png-w331s

然后在 com.sun.org.apache.xpath.internal.objects.XString重寫的equals方法里調用了 tostring ,在 tostring 中調用了 getKey 方法。

ExternalizableHelper#readMap 中會調用 map.putmap.put 會調用 equals 方法。

com.tangosol.util.processor.ConditionalPutAllreadExteranl 中調用了 ExternalizableHelper#readMap 方法。

然后再套上 AttributeHolder 鏈頭就可以了。

具體可以參考:https://mp.weixin.qq.com/s/eyZfAPivCkMbNCfukngpzg

https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210725194322960.png-w331s

4月漏洞修復則是:

添加simpleBianry 到黑名單。

filterExtractor

filterExtractor.reaExternal 方法中的 readAttributeAccessor() 方法會直接 new 一個 MethodAttributeAccessor 對象。 https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210730154428860.png-w331s

https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210730154447677.png-w331s

隨后在 filterExtractor.extract 函數中會因為調用 this.attributeAccessor.getAttributeValueFromObject 進而導致任意無參方法的調用。 https://images.seebug.org/content/images/2021/08/11/1628653082000-image-20210730155415313.png-w331s

涉及 CVE
CVE-2021-2394 (4月)

https://images.seebug.org/content/images/2021/08/11/1628653083000-image-20210730135848902.png-w331s

在4月的補丁中,對 ois 的 DataInput 流進行了過濾,所以直接通過 newInstance 實例化惡意類的方式已經被阻止(CVE-2021-2135 通過 bufferinputStream 進行了繞過),所以需要重新尋找其他不在黑名單中的 readExternal 方法。

CVE-2021-2394 中就是利用 filterExtractor.readExternal 來進行突破。

具體可以參考:https://blog.riskivy.com/weblogic-cve-2021-2394-rce%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/https://www.cnblogs.com/potatsoSec/p/15062094.html

觸發點

ExternalizableHelper.readExternal 的觸發點有 ExternalizableHelper.readObjectExternalizableHelper.fromBinary 這兩個。其中 CVE-2021-2135 則就是因為在 CVE-2020-14756 的修復方法中,只注意到了 ExternalizableHelper.readObject ,只在ExternalizableHelper.readObject 里面做了限制,但是沒有考慮到 ExternalizableHelper.fromBinary 從而導致了繞過。

ExternalizableHelper.readObject可以利用 com.tangosol.coherence.servlet.AttributeHolder來觸發,com.tangosol.coherence.servlet.AttributeHolder 實現了 java.io.Externalizabe 接口,并且他的readExternal 方法 調用了 ExternalizableHelper.readObject(in)https://images.seebug.org/content/images/2021/08/11/1628653084000-image-20210728172300444.png-w331s

ExternalizableHelper.fromBinary 的觸發則較為復雜一些,具體可以參考:https://mp.weixin.qq.com/s/eyZfAPivCkMbNCfukngpzg

后記

weblogic Coherence 反序列化漏洞很多都是相關聯的,對于某個漏洞,很可能就是用到了之前一些漏洞的鏈子。其實不僅僅 weblogic ,java 其他反序列化鏈也是如此,很多情況都是一個鏈會用到其他鏈的一部分。所以在學習中,把一個組件或者一個庫的漏洞總結起來一起分析還是比較重要的,最后希望這篇文章能幫助到其他一起學反序列化的朋友們。

參考

https://nosec.org/home/detail/4524.html

https://cloud.tencent.com/developer/article/1740557

https://blog.riskivy.com/weblogic-cve-2021-2394-rce%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/

https://www.cnblogs.com/potatsoSec/p/15062094.html

https://cert.#/report/detail?id=c8eed4b36fe8b19c585a1817b5f10b9e

https://cert.#/report/detail?id=0de94a3cd4c71debe397e2c1a036436f

https://www.freebuf.com/vuls/270372.html

https://mp.weixin.qq.com/s/E-4wjbKD-iSi0CEMegVmZQ

https://mp.weixin.qq.com/s/eyZfAPivCkMbNCfukngpzg


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1670/