CVE-2021-2135:Weblogic 二次序列化漏洞分析
2021-07-19 16:39

报告编号:B6-2021-071903

报告来源:360CERT

报告作者:360CERT

更新日期:2021-07-19

0x01   漏洞简述

2021年04月21日,360CERT监测发现Oracle官方发布了2021年4月份的安全更新,本次分析报告选取的是其中一个反序列化漏洞,CVE编号为CVE-2021-2135,漏洞等级:严重,漏洞评分:9.8

未经身份验证的攻击者通过T3或IIOP协议发送恶意请求,最终接管服务器。

对此,360CERT建议广大用户及时将Weblogic升级到最新版本。与此同时,请做好资产自查以及预防工作,以免遭受黑客攻击。

0x02   风险等级

评定方式等级
威胁等级严重
影响面广泛
攻击者价值
利用难度
360CERT评分9.8

0x03   漏洞详情

通过官方通告得知该漏洞依然是基于Coherence的反序列化,于是去diffWeblogicFilterConfig,发现黑名单新增一个coherencecom.tangosol.internal.util.SimpleBinaryEntry

此次漏洞是基于CVE-2020-14756漏洞的绕过,采用的思路依然是进行二次反序列化,绕过Weblogic自身jep290的黑名单限制。在SimpleBinaryEntry里存在getKey/getValue方法,这两个方法都调用了ExternalizableHelper.fromBinary方法。

fromBinary方法里又调用了deserializeInternal,在该方法里会将ReadBuffer类型的输入流转换为BufferInput类型,传入readObjectInternal方法,

接着,调用readExternalizableLite方法。

CVE-2020-14756中,对该方法进行了修复。

修复的原理是,只要输入流的类型是ObjectInputStream,那么会去调用checkObjectInputFilter方法,而checkObjectInputFilter的具体实现其实就是基于jep290的检测。

但是,当我们通过BufferInput流进行反序列化的时候,是不会被调用到checkObjectInputFilter方法的,于是绕过了之前的补丁。

POC构造

SimpleBinaryEntrygetKey方法在自身重写的toString方法内进行了调用。

那么首先要想办法触发toString方法,最开始我想到的是BadAttributeValueExpException,直接反序列化的时候就会调用对象的toString方法,不过这样就会有问题。 在最终调用serializer.deserialize进行二次序列化的时候,serializer会因为没有赋值而报错,SimpleBinaryEntry自身有一个setContextSerializer方法,需要有地方能调用。

serializer的赋值在ExternalizableHelper#readExternalizableLite

所以,还是需要先有流程走到ExternalizableHelper#readExternalizableLite,这里只需要valueSimpleBinaryEntry就能设置 serializer 。 参考了漏洞发现者的文章,toString方法能够在com.sun.org.apache.xpath.internal.objects.XString重写的equals方法里调用。

ExternalizableHelper#readMap方法里调用了map.put,熟悉反序列化的应该都很熟悉put方法,在map.put方法里会触发keyequals方法的调用,而这里的oKeyoVal都是可以通过序列化进行控制的,只需要oKeyXString类型即可。

接着还需要有一个调用readMap的地方,com.tangosol.util.processor.ConditionalPutAllreadExternal方法中刚好就存在readMap的调用。

看似已经没有问题了,但是这个类并不是Externalizable的子类,所以在反序列化的调用中,无法自动调用到readExternal方法,所以还是需要找另外一个入口来主动调用他的readExternal。 这里就可以参考CVE-2020-14756了,入口类com.tangosol.coherence.servlet.AttributeHolder没有加到黑名单里。

完整的调用栈如下:

漏洞证明

PatchID: 32124456

漏洞修复

第一个修复的点依旧是针对黑名单,加入了SimpleBinaryEntry类。 第二个修复点就是本次修复大改的地方,加入了白名单机制,只允许白名单里的类或其子类通过白名单。 打了补丁后,再次发送攻击的包会报错,调用栈在log里清晰可见:

于是我们看到weblogic.rjvm.InboundMsgAbbrev,新增了一个白名单字段。

private static final Class[] ABBREV_CLASSES = new Class[]{String.class, ServiceContext.class, ClassTableEntry.class, JVMID.class, AuthenticatedUser.class, RuntimeMethodDescriptor.class, Immutable.class};

InboundMsgAbbrev里的readObject方法将白名单传入了readObjectValidated方法

会设置expectedType,即白名单List。

T3自身的序列化流程走完之后,就开始走ObjectInputStream,在调用到ServerChannelInputStream重写的resolveClass的时候,先进行黑名单检测。

如果不在黑名单里,继续调用super.resolveClass,这个时候会调用validateReturnType方法 。

这里,进行了白名单检测,从expectedType取值,只要不是白名单里的子类型,那么就会直接报错。

0x04   时间线

2021-04-20 Oracle发布安全更新通告

2021-04-21 360CERT发布通告

2021-07-19 360CERT发布分析

0x05   参考链接

1、 Oracle Critical Patch Update Advisory - April 2021

2、 How Did I Find Weblogic T3 RCE

0x06   特制报告下载链接

一直以来,360CERT对全球重要网络安全事件进行快速通报、应急响应。为更好地为政企用户提供最新漏洞以及信息安全事件的安全通告服务,现360CERT正式推出安全通告特制版报告,以便用户做资料留存、传阅研究与查询验证。 用户可直接通过以下链接进行特制报告的下载。

CVE-2021-2135:Weblogic 二次序列化漏洞分析

若有订阅意向与定制需求请发送邮件至 g-cert-report#360.cn ,并附上您的 公司名、姓名、手机号、地区、邮箱地址。