问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
CVE-2020-14756 漏洞利用以及分析
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`接口。 ![image](https://shs3.b.qianxin.com/butian_public/f8e0a673ba37953ab24b7341e12d1acd4.jpg) `readExternal`和`writeExternal`方法 ![image](https://shs3.b.qianxin.com/butian_public/f899e2fd7183103cd4dabd9743cfc1180.jpg) 而`ExternalizableLite`接口的对象可以在`com.tangosol.util.ExternalizableHelper`里被序列化。 ![image](https://shs3.b.qianxin.com/butian_public/ff99403b8008625936e4e5aba63c34932.jpg) 这里的`nType`是在writeObject写入的,是可控的 ![image](https://shs3.b.qianxin.com/butian_public/ffb39fcff02c5a9414655926e9a999dce.jpg) `readExternalizableLite`方法的具体内容为: 这里会加载传入的对象,对象需要是`ExternalizableLite`的实现类 ![image](https://shs3.b.qianxin.com/butian_public/fff5f059e65117ded8ce9cedf2c4f0348.jpg) 这里直接调用`class.forName`还原对象 ![image](https://shs3.b.qianxin.com/butian_public/f956537f89b29fede777551f530bb6ede.jpg) 之后,会继续调用对象的`readExternal`方法,这样一来,后续的流程就绕过了ObjectInputStream对于对象的还原,而weblogic的黑名单检测也主要是针对`ObjectInputStream`的,所以,现在只需要找到后续的利用链就可以造成代码执行。 漏洞发现者使用了`com.tangosol.util.aggregator.TopNAggregator.PartialResult`这个类。这里会利用`ExternalizableHelper`还原`m_comparator`参数,是一个`Comparator`类型的对象。 ![image](https://shs3.b.qianxin.com/butian_public/fb17fff39d076644ca9ebe81740fc108e.jpg) 然后调用了`instantiateInternalMap`方法,传入`m_comparator` ![image](https://shs3.b.qianxin.com/butian_public/f7dfb537747292abcbd2a6092f3f321f3.jpg) 首先实例化`SortedBag.WrapperComparator`,赋值`f_comparator`,然后返回`TreeMap`对象 ![image](https://shs3.b.qianxin.com/butian_public/fbc413bc5ec1efcfc69ad588898bb514c.jpg) 接着,调用add方法,在add方法里调用`super.add`,即`SortedBag.add`,继续调用`put`方法。 ![image](https://shs3.b.qianxin.com/butian_public/f55826c195ffcbe443e5fd5c1e780f9cf.jpg) 在`put`方法里,调用了`compare`方法 ![image](https://shs3.b.qianxin.com/butian_public/f7edf0da04db0d4a0cfccbf4b23462c7f.jpg) 而这里又会调用`WrapperComparator`的`compare`方法 ![image](https://shs3.b.qianxin.com/butian_public/fa806132b5d744070bb0217da836527bd.jpg) 这个`f_comparator`就是之前已经赋值过的。 ![image](https://shs3.b.qianxin.com/butian_public/f727b55a405328bf85fddfa67b4d4c2a2.jpg) 所以,最终的利用就在`f_comparator`这里,`f_comparator`从前面可以知道,需要是一个`Comparator`类型,这里使用的是 `MvelExtractor` 这是之前黑名单里的一个类,在CVE-2020-2555中有使用,不过现在我们不受黑名单的限制,`MvelExtractor` 没有`compare`方法。于是调用父类`AbstractExtractor`的`compare`方法。 ![image](https://shs3.b.qianxin.com/butian_public/fe125bb1430e4ced96846912ba9c8c58d.jpg) 然后又会调用子类`MvelExtractor`的`extract`方法。 #### 序列化入口一 到现在我们的入口是`TopNAggregator$PartialResult`,他的`readExternal(DataInput in)`不是标准的`readExternal(ObjectInput in)`,序列化的过程中是不会自动调用到该方法的,所以还需要找一个入口,这里作者发现了`AttributeHolder`。 这里不但会将`ObjectInput`转为`DataInput`,还会主动调用`ExternalizableHelper.readObject`。所以我们只需要`m_oValue`是`TopNAggregator$PartialResult`即可完成利用。 ![image](https://shs3.b.qianxin.com/butian_public/fe4d17bf6f3671c94c0a617afcf239c8d.jpg) 调用栈 ![image](https://shs3.b.qianxin.com/butian_public/f76bc5bb03d446c9a4e949d44f715396f.jpg) #### 序列化入口二 另外一个入口是`com.tangosol.net.security.PermissionInfo`,我们看他的`readExternal`方法,将输入流传入`readCollection`方法里,`PermissionInfo`是`ExternalizableHelper`的子类,所以这里`PermissionInfo`没有`readCollection`方法,直接调用其父类`ExternalizableHelper`的方法。 ![image](https://shs3.b.qianxin.com/butian_public/ff233fd942c37c9d6bd6c9ae7775e93d3.jpg) 判断输入流类型之后,调用了`readObject`。 在调用`readCollection`的时候,将`ObjectInput`转为了`DataInput` ![image](https://shs3.b.qianxin.com/butian_public/fc0b6f3dea44c334d362fa19d88dddb45.jpg) 走到这里,就和之前的流程一模一样了。 ![image](https://shs3.b.qianxin.com/butian_public/f4783ee13fb5327369fba0f659bb4b36f.jpg) 调用栈 ![image](https://shs3.b.qianxin.com/butian_public/f00c851df0ff94fead375f529a69a95bd.jpg) ### 0x03 12.1.3版本问题 经测试,`12.1.3` 利用存在如下问题 ![image](https://shs3.b.qianxin.com/butian_public/fbd537b15b174a6f805ae17d5b0d583f9.jpg) 从前面的分析可以知道,类的加载是在`loadClass`方法里,利用`class.forName`去加载类。 ![image](https://shs3.b.qianxin.com/butian_public/f149139c4a1b7a208971a813e9d640653.jpg) 这里的`loader`就很关键了,决定了哪些类可以加载,哪些类没发加载,这里的`loader`是调用`getContextClassLoader`获得的一个线程上下文类加载器。 ![image](https://shs3.b.qianxin.com/butian_public/f42109923d85b38fad56f1c37531320d7.jpg) 这里的线程上下文类加载器是默认的 `AppClassLoader`,在`loaders`里发现`JarLoader`加载了的`coherence`组件的依赖只有`coherence.jar`和`coherence-web.jar`,而`MvelExtractor`在`coherence-rest.jar`里,所以没有办法加载。 ![image](https://shs3.b.qianxin.com/butian_public/fdaf7ca87de08a32e2d12834d182d03f1.jpg) ![image](https://shs3.b.qianxin.com/butian_public/fb97469746ab7c52f30c83d7268d10f08.jpg) 以下是一些尝试(未成功): 于是我这里先是考虑了另一个在黑名单的类,`ReflectionExtractor`,这个类在`coherence.jar`包下,不过在构造利用这个反射执行链的时候,需要反序列化`Runtime.class`对象,而`Runtime.class`对象不是`ExternalizableLite`的实现类,根据`nType`,在序列化的时候会调用`readSerializeable`方法 ![image](https://shs3.b.qianxin.com/butian_public/f48e3b53a73bde0f51c581252bc98c500.jpg) 该方法还是会走`ObjectInputStream`的反序列化流程,即使是通过修改`nType`让他走`readExternalizable`,后面还是会有类型转换报错。 ![image](https://shs3.b.qianxin.com/butian_public/fdfa3b0b605aceecb5e0f69bdb02c8e28.jpg) 所以这样是不行的,12.1.3版本很多类都利用不了,比如`RemoteConstructor`、`UniversalExtractor`、`LockVersionExtractor`这些类在 `12.1.3` 版本中都没有,已知的利用链在 12.1.3 来说是没有办法进行利用的。 ### 0x04官方修复之梅开二度 (补丁只能针对实现了`jep290`的`jdk`) 根据补丁来看: ![image](https://shs3.b.qianxin.com/butian_public/f272da1177e8e7934158721b04f42fe8c.jpg) 对输入流的类型进行了判断,如果是`ObjectInputStream`,那么会去调用`checkObjectInputFilter`方法,方法如下: ![image](https://shs3.b.qianxin.com/butian_public/f16ce781802c94a3312f9e21bbdf16cd6.jpg) 这里会获取`filter`,在`ExternalizableHelper`的静态代码块里初始化了`filter` 首先会获取是否存在`ObjectInputFilter`,来判断`jdk`环境中是否存在`jep290`。 ![image](https://shs3.b.qianxin.com/butian_public/f8c77ce32977359fda30630001f0cc4bd.jpg) 然后通过`getObjectInputFilter/getInternalObjectInputFilter`方法去获取`serialFilter`,之后,调用`checkInput`,对当前序列化的类进行检测。 不过,对于没有实现`jep290`的`jdk`版本而言,这个修补是没有作用的,因为低版本`jdk`不存在`ObjectInputFilter`,所以说`filter`参数就为`null`,也就是说`checkObjectInputFilter`方法直接返回`true`。 ![image](https://shs3.b.qianxin.com/butian_public/fecbadb6e0cde859b37a9d235451e4e9a.jpg) 既然为`true`,那么还是能进行类的实例化。 ![image](https://shs3.b.qianxin.com/butian_public/f7556ea82fbfe5c9ccc50b17323c1fe50.jpg)
发表于 2021-04-07 20:01:06
阅读 ( 6241 )
分类:
漏洞分析
1 推荐
收藏
0 条评论
请先
登录
后评论
带头大哥
50 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!