【漏洞分析】Weblogic反序列化漏洞分析(CVE-2021-2394)

2021-09-14 09:54:38 浏览数 (1)

本文字数:1913

阅读时长:4~6min

声明:仅供学习参考使用,请勿用作违法用途,否则后果自负

0x01 漏洞复现

《CVE-2021-2394:Weblogic反序列化漏洞复现》

0x02 调试准备

生成wlfullclient.jar包:来到wlserverserverlib下运行java -jar ../../modules/com.bea.core.jarbuilder.jar将在lib目录下生成一个wlfullclient.jar包,该jar包包含了weblogic的基本所有功能类,用于IIOP协议发包,有效解决了jar包冲突问题

添加依赖包,经过测试,需要添加的包如下图,均可在weblogic的安装目录下找到

这里选择本地调试,输出序列化文件再调用readObject()即可

0x03 漏洞分析

在正式分析CVE-2021-2394之前,有必要回顾一下CVE-2020-14825

CVE-2020-14825的调用链如下:

前半部分属于典型的CC2的入口,能够调用实现了Comparator接口的compare方法,这里选择了ExtractorComparator,里面能够调用实现了ValueExtractor接口的extract方法

而在LockVersionExtractor#extract中,调用了accessor的initializeAttributes和getAttributeValueFromObject方法

在MethodAttributeAccessor#getAttributeValueFromObject中,存在利用反射执行方法(需要注意的是,由于传入getAttributeValueFromObject的parameters参数为null,故只能调用无参的方法,这也是我们选择JdbcRowSetImpl类作为我们利用点的原因)

但由于MethodAttributeAccessor的getMethod使用了transient修饰,所以需要通过别的方法给他赋值,在initializeAttributes中则有setGetMethod的调用来设置getMethod

故我们可以让LockVersionExtractor的accessor为MethodAttributeAccessor使其给getMethod赋值后通过反射执行方法。现在再回去看14825调用链和POC应该不难理解(attributeName不能为空,防止他报错,设置WriteOnly且不设置setMethod是因为当他是WriteOnly时可以不设置setMethod)

回到CVE-2021-2394,在Oracle把LockVersionExtractor和MethodAttributeAccessor(所在的包)加入黑名单后,漏洞发现者使用FilterExtractor对其进行绕过

在FilterExtractor#extract中也存在和LockVersionExtractor#extract类似的调用

更厉害的是,在FilterExtractor#readExternal中,调用了SerializationHelper#readAttributeAccessor,该方法实例化了一个MethodAttributeAccessor,最后把其作为this.attributeAccessor的值

这就基本上接上去了,现在主要的问题就是如何先调用FilterExtractor#readExternal后调用FilterExtractor#extract呢?这时候不难想起CVE-2020-14756了,以下是调用链:

com.tangosol.util.aggregator.TopNAggregator$PartialResult#readExternal中,先是利用ExternalizableHelper#readObject反序列化了comparator赋值给m_comparator,再用m_comparator生成了一个map,再调用add方法往map里添加数据

先跟一下ExternalizableHelper#readObject,如果是实现了ExternalizableLite接口的将调用readExternalizableLite方法,该方法通过类加载的形式实例化了对象,并调用了得到的对象的readExternal方法

PartialResult#instantiateInternalMap利用m_comparator实例化了一个TreeMap

再跟一下PartialResult#add,调用了com.tangosol.util.SortedBag#add,该方法拿到了刚才实例化好的TreeMap,调用put方法放数据

SortedBag#add

TreeMap#put调用了this.comparator#compare,最后会调用AbstractExtractor#compare方法,其调用了this.comparator#extract方法

整理一下

现在都满足了我们的要求,就可以直接接上去了

通过以上分析我们应该可以自己构造POC了,把CVE-2020-14825和CVE-2020-14756的POC稍微拼接一下就行

以下是调用链:

在构造POC时有几个需要注意的点:

在这个CVE中,通过SerializationHelper#readAttributeAccessor实例化了一个MethodAttributeAccessor并对其进行字段进行赋值,但是只是赋值了attributeName 、getMethod 和setMethod,并没有我们之前提到的WriteOnly,他的值默认为false

如果WriteOnly为false则会去获取setSetMethod,他会根据getMethod返回值的类型作为获取setMethod的参数,如果不匹配则因为找不到对应的setMethod方法而报错

这里找到了符合要求的方法:JdbcRowSetImpl#connect()为getMethod,JdbcRowSetImpl#setConnect()为setMethod

此外,在构造IIOP协议发包的时候,踩了好久的坑,这里也分享一下。

IIOP协议发包我是直接参考了Y4er师傅的CVE-2020-2551的POC(见参考链接),POC中提到的需要添加weblogic.jar包,我在12.2.1.3.0中测试,发现不太行,缺少一些依赖(找不到IIOP协议等错误),对比10.3.6.0的weblogic.jar包,12.2.1.3.0是缺少了挺多类的,因此我去添加了一些其他的同目录下用于数据传输的包,效果不太理想,不同包之间会有比较大的冲突。

最后我找到了一位师傅复现CVE-2020-14644的文章(见参考链接),将wlserver/modules下的功能类打包成一个jar包,完美解决了问题。(其实Y4er师傅的jar包也使用了这个jar包,我当时没多注意: ( 导致浪费了很多时间)。

此外,在我放到github的POC中,利用IIOP协议发包的时候,我有一些奇奇怪怪的东西没删掉。

0x04 个人总结

CVE-2020-14825LockVersionExtractorMethodAttributeAccessor被加入黑名单后,漏洞发现者利用FilterExtractor这个类,他的readExternal方法可以实例化一个MethodAttributeAccessor,并将其赋值给自己的attributeAccessor,再加上他的extract方法存在类似LockVersionExtractor#extract的调用,从而接上了原来的利用链。

weblogic的补丁经常是把之前CVE所利用到的类的包加入黑名单(这次好像还修了iiopinputstream)导致有很多师傅去找能够代替的链,很多CVE就是这么来的。在14825的补丁之上,2394的漏洞发现者找到了一个能够代替LockVersionExtractor的类,他的readExternal又实例化了MethodAttributeAccessor,感觉这个思路很强,利用一些方法实例化了黑名单中的类。

2394外,在Oracle的四月份安全更新上,有一个漏洞编号为CVE-2021-2135的CVE则通过SimpleBinaryEntry调用了ExternalizableHelper.fromBinary方法读取数据流进行反序列化,没有使用打了补丁的ObjectInputStream(指黑名单类没有经过ObjectInputStream),从而绕过14825的补丁,也是一个值得学习的思路(见参考链接最后一个)。不出意外过段时间会有一篇CVE-2021-2135的分析(虽然参考链接那篇文章已经很详细了)

代码语言:javascript复制
参考链接:

https://paper.seebug.org/1655/

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

https://github.com/Y4er/CVE-2020-2551

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

https://cert.360.cn/report/detail?id=0a561500f30aaad6b00d814b2c707667

0 人点赞