本文字数: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-14825
的LockVersionExtractor
和MethodAttributeAccessor
被加入黑名单后,漏洞发现者利用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
的分析(虽然参考链接那篇文章已经很详细了)
参考链接:
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