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

处理流程:

  1. 初始化并跳过4字节的长度信息
  2. 读取header信息(weblogic.rjvm.JVMMessage#readHeader
  3. 标记当前位置并跳过部分内容
  4. 调用connection.readMsgAbbrevs(this)进行反序列化

Header结构(共19字节):

  • cmd:执行指令,影响处理分支
  • QOS:服务质量标志
  • flags:标志位,影响处理分支
  • responseId:响应ID
  • invokableId:可调用ID
  • abbrevOffset:header长度标识

2. 白名单机制分析

2021年4月补丁后,Weblogic实施了严格的白名单机制,仅允许以下7种类被反序列化:

  1. java.lang.String
  2. weblogic.rmi.spi.ServiceContext
  3. weblogic.rjvm.ClassTableEntry
  4. weblogic.rjvm.JVMID
  5. weblogic.security.acl.internal.AuthenticatedUser
  6. weblogic.rmi.extensions.server.RuntimeMethodDescriptor
  7. 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);
}

绕过要点:

  1. readClassDescriptor()从ClassTableEntry中读取descriptor属性
  2. resolveClass()方法只有黑名单检查,没有白名单限制
  3. 可以实例化实现了Externalizable接口的类并调用其readExternal方法

3.2 绕过限制的关键点

  1. 不能直接使用原生readObject

    • 在Externalizable实例的readExternal中调用原生readObject仍会受白名单限制
    • 因为使用的是同一个流对象
  2. 流转换机制

    • 通过ExternalizableHelper.readObject方法可以实现流转换
    • 特别是readSerializable方法会创建新的WLSObjectInputStream

3.3 具体绕过方法

  1. 利用ClassTableEntry(在白名单中)传递恶意descriptor
  2. 触发Externalizable接口实现类的readExternal方法
  3. 通过ExternalizableHelper.readObject创建新的WLSObjectInputStream
  4. 在新的流中执行不受限制的反序列化

关键调用栈:

ExternalizableHelper.readObject()
  -> getObjectInput()
    -> new WLSObjectInputStream()

4. 实现细节与注意事项

4.1 数据构造要点

  1. Header构造

    • 设置适当的flags值以进入read81Contexts分支
    • 确保abbrevOffset值正确
  2. Payload构造

    • 使用ClassTableEntry传递恶意descriptor
    • 选择适当的Externalizable实现类

4.2 可用类分析

  1. weblogic.cache.RefWrapper

    • 实现了Externalizable接口
    • 但直接使用其readExternal会触发原生readObject
  2. com.tangosol.coherence.servlet.AttributeHolder

    • 使用ExternalizableHelper.readObject
    • 可能实现流转换

4.3 实际利用难点

  1. 字节码构造:

    • 需要手动修改某些字段
    • 程序自身序列化的数据可能无法直接使用
  2. WLSObjectInputStream处理:

    • 需要构建符合要求的数据流
    • 可能需要深入研究其内部实现

5. 防御与检测建议

5.1 防御措施

  1. 禁用不必要的T3协议
  2. 及时应用最新补丁
  3. 实施网络层访问控制

5.2 检测方法

  1. 监控异常T3协议流量
  2. 检查可疑的ClassTableEntry使用
  3. 关注Externalizable接口的异常调用

6. 总结

本文详细分析了Weblogic T3协议白名单绕过的技术原理,关键在于利用ClassTableEntry传递恶意descriptor,并通过Externalizable接口实现类的readExternal方法触发流转换,最终在新建的WLSObjectInputStream中实现不受限制的反序列化操作。实际利用中需要注意字节码构造和流处理的细节问题。

Weblogic T3协议白名单绕过方法深度解析 1. T3协议基础交互流程 1.1 协商阶段 Weblogic处理T3基础信息协商的核心类: weblogic.rjvm.t3.MuxableSocketT3#readIncomingConnectionBootstrapMessage 客户端发送格式 : 服务端响应格式 : 关键点: 客户端发送的是键值对形式 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 方法中存在关键代码段: 绕过要点: 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 在新的流中执行不受限制的反序列化 关键调用栈: 4. 实现细节与注意事项 4.1 数据构造要点 Header构造 : 设置适当的flags值以进入 read81Contexts 分支 确保abbrevOffset值正确 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中实现不受限制的反序列化操作。实际利用中需要注意字节码构造和流处理的细节问题。