zoukankan      html  css  js  c++  java
  • Oracle cve 2020-14644 分析利用以及回显思路

    0x00 前置知识

    1. classloader defineClass

    该方法允许将符合class格式的bytes数组,作为类去加载。该方法返回一个Class对象。

    一般情况下,通过defineClass加载的类,不允许同名,否则会报错,切记

    2. java asm& javaassist

    既然上面说了,defineClass不允许加载同名类。所以我们需要动态构建class,并生成bytes数组。在java中一般使用asm或者javaassist通过jvm字节码,直接生成一个class。两种各有优缺点。

    1. asm语法复杂,需要熟悉jvm底层知识。运行速度快
    2. javaassist 语法简单,运行速度慢

    在这里推荐一个asm插件,可以将class一键转换为asm的java代码,并输出bytes。然后再按需修改class的相关参数

    3. java反序列化的transient参数

    protected transient Class<? extends Remotable> m_clz;
    protected transient MethodHandle m_mhCtor;
    
    

    transient参数修饰的变量,是不参与反序列化的。最终变量值为null

    0x01 cve-2020-14644 漏洞分析

    简单来讲,该漏洞在反序列化时通过defineClass直接加载类。下面是待加载的类

    下面我们从RemoteConstructor的newInstance开始分析,断点设置以及调用堆栈如下

    newInstance的代码如下

        public T newInstance() {
            RemotableSupport support = RemotableSupport.get(this.getClassLoader());
            return support.realize(this);
        }
    

    RemotableSupport可以认为是coherence自定义的Classloader。RemotableSupport中实现了defineClass。下面我们跟入RemotableSupport的realize方法,看一下realize方法都做了什么

        public <T> T realize(RemoteConstructor<T> constructor) {
            ClassDefinition definition = this.registerIfAbsent(constructor.getDefinition());
            Class<? extends Remotable> clz = definition.getRemotableClass();
            if (clz == null) {
                synchronized(definition) {
                    clz = definition.getRemotableClass();
                    if (clz == null) {
                        definition.setRemotableClass(this.defineClass(definition));
                    }
                }
            }
    
            Remotable<T> instance = (Remotable)definition.createInstance(constructor.getArguments());
            instance.setRemoteConstructor(constructor);
            return instance;
        }
    

    首先从RemoteConstructor中获取m_definition,类型为ClassDefinition。随后调用m_definition的getRemotableClass方法。这一句是关键。我们去看一下m_definition的getRemotableClass方法

    可以很明显的看到getRemotableClass方法返回的m_clz,是通过transient修饰的。所以在反序列化后,这里一定返回null。

    于是就会走到if条件的另外一个分支,调用this.defineClass(definition)去加载类。通过RemotableSupport去根据给定的参数,创建一个类。

    RemotableSupport的defineClass方法就很简单了。从ClassDefinition中获取类名,类的bytes字节,调用系统的classloader去创建一个类

        protected Class<? extends Remotable> defineClass(ClassDefinition definition) {
            String sBinClassName = definition.getId().getName();
            String sClassName = sBinClassName.replace('/', '.');
            byte[] abClass = definition.getBytes();
            definition.dumpClass(DUMP_REMOTABLE);
            return this.defineClass(sClassName, abClass, 0, abClass.length);
        }
    

    所以payload代码如下

    在这里我们只需要通过iiop协议,直接将RemoteConstructor对象发送给weblogic服务即可

    0x02 回显利用

    在cve-2020-2551 回显利用中,因为classloader的问题,我们需要上传一个jar包,并区分windows与linux操作系统才可以通过URLClassloader去正确加载上传的jar包。但是通过该漏洞,我们发现,可以直接写好类,并转换为bytes字节,通过反序列化发送给weblogic服务器即可。

    至于回显,无非就是给服务器安装一个JNDI实例即可。所以我们需要加载的类的代码如下

    运行结果如下

    目前代码已上传至 https://github.com/potats0/cve_2020_14644

    后台回复14644获取工具下载

    0x03 参考

    1. https://paper.seebug.org/1281/

    欢迎关注 宽字节安全 公众号

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    数据库作业5:SQL练习2
    数据库作业4:SQL练习1
    Linux的cp复制和mv移动命令的超详细介绍
    python数组添加整行或整列
    CentOS7下安装tomcat的超详细说明
  • 原文地址:https://www.cnblogs.com/potatsoSec/p/13451993.html
Copyright © 2011-2022 走看看