Weblogic CVE-2016-0638 StreamMessageImpl绕过黑名单
环境
采用上次的环境,然后打两个补丁
详细安装步骤参考https://xz.aliyun.com/t/8701#toc-2
补丁分析
补丁修改过以下三个类
weblogic.rjvm.InboundMsgAbbrev.class#ServerChannelInputStream
weblogic.rjvm.MsgAbbrevInputStream.class
weblogic.iiop.Utils.class
首先来看看导致CVE-2015-4852漏洞的weblogic.rjvm.InboundMsgAbbrev.class#ServerChannelInputStream

增添了一个黑名单判断,跟进黑名单看看
org.apache.commons.collections.functors,
com.sun.org.apache.xalan.internal.xsltc.trax,
javassist,
org.codehaus.groovy.runtime.ConvertedClosure,
org.codehaus.groovy.runtime.ConversionHandler,
org.codehaus.groovy.runtime.MethodClosure
在黑名单处打个断点,用上次的exp打一下

捕捉到了org.apache.commons.collections.functors.ChainedTransformer
,而抛出异常

weblogic.rjvm.MsgAbbrevInputStream
也是同样的修补方法,以此类推

现在需要找到一个未使用黑名单的类调用readObject()方法进行反序列化的数据的读取,执行含有恶意代码的序列化代码。weblogic.jms.common.StreamMessageImpl#readExternal
Exp分析
这里来分析https://github.com/5up3rc/weblogic_cmd
项目的EXP
配置参数
-H "10.216.6.173" -C "touch /tmp/hacked_by_le1a" -B -os linux

在executeBind()
打下断点


从参数获取命令C为touch /tmp/hacked_by_le1a
,继续跟进WebLogicOperation#blindExecute()

这里将命令作为参数传入函数,再继续跟进SerialDataGenerator#serialBlindDatas()


这一段就很熟悉了,cc1中创建ChainedTransformer的片段。加下来看serialData()
的操作

这里有两个注意的点:
- 把刚刚
return
的transformers
给生成ChainedTransformer
- 最后这里,本应该把handler对象序列化,但这里是将
handler的序列化数据
传入streamMessageImpl
包装


接着进入T3协议 T3ProtocolOperation.send(host, port, payload)
,然后就是构造T3协议,发送出去。



这里v4接受反序列化数据,v5执行了反序列化操作,导致恶意代码被执行
绕过原理
将反序列化的对象封装进了 StreamMessageImpl,然后对 StreamMessageImpl 进行序列化,生成 payload 字节码。反序列化时 StreamMessageImpl 不在 WebLogic 黑名单里,可正常反序列化。在反序列化时 StreamMessageImpl 对象调用 readObject 时,对 StreamMessageImpl 封装的序列化对象再次反序列化,这样就逃过了黑名单的检查。

这里获取到的类是StreamMessageImpl
而不再是AnnotationInvocationHandler
,也就是说黑名单当中的org.apache.commons.collections.functors.ChainedTransformer
并不会再此出现。
这里的反序列化,仅对StreamMessageImpl
反序列化,而恶意的序列化数据被StreamMessageImpl
包装,真正执行恶意代码的过程,在StreamMessageImpl
内部二次反序列化触发。
参考
https://xz.aliyun.com/t/8701
https://y4er.com/posts/weblogic-cve-2016-0638/