Weblogic T3协议白名单绕过方法探索
字数 2111 2025-08-29 08:32:01
Weblogic T3协议白名单绕过方法深度解析
1. T3协议基础交互流程
1.1 协商阶段
Weblogic处理T3基础信息协商的核心类:
weblogic.rjvm.t3.MuxableSocketT3#readIncomingConnectionBootstrapMessage
客户端发送格式:
t3 10.3.6
AS: 255
HL: 19
服务端响应格式:
HELO: 12.2.1.4 . false
AS: 2048
HL: 19
MS: 10000000
PN: DOMAIN
关键点:
- 客户端发送的是键值对形式
- AS和HL是常用头信息(AS建议设置为01以尽可能小)
1.2 信息发送阶段
核心处理类:
weblogic.rjvm.MsgAbbrevInputStream#init
处理流程:
- 初始化并跳过4字节的长度信息
- 读取header信息(
weblogic.rjvm.JVMMessage#readHeader) - 标记当前位置并跳过部分内容
- 调用
connection.readMsgAbbrevs(this)进行反序列化
Header结构(共19字节):
- cmd:执行指令,影响处理分支
- QOS:服务质量标志
- flags:标志位,影响处理分支
- responseId:响应ID
- invokableId:可调用ID
- abbrevOffset:header长度标识
2. 白名单机制分析
2021年4月补丁后,Weblogic实施了严格的白名单机制,仅允许以下7种类被反序列化:
- java.lang.String
- weblogic.rmi.spi.ServiceContext
- weblogic.rjvm.ClassTableEntry
- weblogic.rjvm.JVMID
- weblogic.security.acl.internal.AuthenticatedUser
- weblogic.rmi.extensions.server.RuntimeMethodDescriptor
- weblogic.utils.io.Immutable
3. 白名单绕过原理
3.1 关键突破口
在read81Contexts方法中存在关键代码段:
if (b == 4) {
ObjectStreamClass desc = this.readClassDescriptor();
Class cl = this.resolveClass(desc);
weblogic.utils.io.ObjectStreamClass osc = weblogic.utils.io.ObjectStreamClass.lookup(cl);
Externalizable e = (Externalizable)osc.newInstance();
int envelopeLength = this.readInt();
int startEnvelope = this.pos();
this.pushExternalizableInfo(startEnvelope + envelopeLength, cl.getName());
e.readExternal(this);
}
绕过要点:
readClassDescriptor()从ClassTableEntry中读取descriptor属性resolveClass()方法只有黑名单检查,没有白名单限制- 可以实例化实现了Externalizable接口的类并调用其readExternal方法
3.2 绕过限制的关键点
-
不能直接使用原生readObject:
- 在Externalizable实例的readExternal中调用原生readObject仍会受白名单限制
- 因为使用的是同一个流对象
-
流转换机制:
- 通过
ExternalizableHelper.readObject方法可以实现流转换 - 特别是
readSerializable方法会创建新的WLSObjectInputStream
- 通过
3.3 具体绕过方法
- 利用
ClassTableEntry(在白名单中)传递恶意descriptor - 触发
Externalizable接口实现类的readExternal方法 - 通过
ExternalizableHelper.readObject创建新的WLSObjectInputStream - 在新的流中执行不受限制的反序列化
关键调用栈:
ExternalizableHelper.readObject()
-> getObjectInput()
-> new WLSObjectInputStream()
4. 实现细节与注意事项
4.1 数据构造要点
-
Header构造:
- 设置适当的flags值以进入
read81Contexts分支 - 确保abbrevOffset值正确
- 设置适当的flags值以进入
-
Payload构造:
- 使用
ClassTableEntry传递恶意descriptor - 选择适当的
Externalizable实现类
- 使用
4.2 可用类分析
-
weblogic.cache.RefWrapper:
- 实现了Externalizable接口
- 但直接使用其readExternal会触发原生readObject
-
com.tangosol.coherence.servlet.AttributeHolder:
- 使用ExternalizableHelper.readObject
- 可能实现流转换
4.3 实际利用难点
-
字节码构造:
- 需要手动修改某些字段
- 程序自身序列化的数据可能无法直接使用
-
WLSObjectInputStream处理:
- 需要构建符合要求的数据流
- 可能需要深入研究其内部实现
5. 防御与检测建议
5.1 防御措施
- 禁用不必要的T3协议
- 及时应用最新补丁
- 实施网络层访问控制
5.2 检测方法
- 监控异常T3协议流量
- 检查可疑的ClassTableEntry使用
- 关注Externalizable接口的异常调用
6. 总结
本文详细分析了Weblogic T3协议白名单绕过的技术原理,关键在于利用ClassTableEntry传递恶意descriptor,并通过Externalizable接口实现类的readExternal方法触发流转换,最终在新建的WLSObjectInputStream中实现不受限制的反序列化操作。实际利用中需要注意字节码构造和流处理的细节问题。