从防护角度看Weblogic反序列化历史漏洞
字数 2528 2025-08-18 11:39:26

Weblogic反序列化漏洞深度分析与防护指南

一、Weblogic反序列化漏洞概述

Weblogic反序列化漏洞是一个经典的漏洞系列,根源在于Weblogic(及其他很多Java服务器应用)在通信过程中传输数据对象,涉及到序列化和反序列化操作。如果能找到某个类在反序列化过程中能执行某些奇怪的代码,就有可能通过控制这些代码达到RCE(远程代码执行)的效果。

序列化与反序列化基础

  • 序列化:将对象转换为字节序列的过程
  • 反序列化:将字节序列恢复为对象的过程
  • 关键机制
    • 实现Serializable接口的类支持序列化
    • 可选择实现writeObject/readObjectwriteExternal/readExternal方法
    • readObject方法在反序列化时被调用,是漏洞利用的关键点

二、Weblogic历史漏洞分类与详细分析

2.1 T3协议直接利用漏洞

2.1.1 CVE-2015-4582(Commons Collections漏洞)

漏洞原理

  • 利用commons-collections:3.1库中的AnnotationInvocationHandler
  • 调用链:
    ObjectInputStream.readObject()
    AnnotationInvocationHandler.readObject()
    Map(Proxy).entrySet()
    AnnotationInvocationHandler.invoke()
    LazyMap.get()
    ChainedTransformer.transform()
    InvokerTransformer.transform()
    Method.invoke()
    Runtime.exec()
    

关键类

  • AnnotationInvocationHandler:触发反序列化入口
  • LazyMap:实现Map接口,key不存在时通过Transformer生成value
  • InvokerTransformer:执行任意方法调用
  • ChainedTransformer:链式执行多个Transformer

实际调用栈

readObject:312, AnnotationInvocationHandler
readObject0:1328, ObjectInputStream
readObject:350, ObjectInputStream
readObject:66, InboundMsgAbbrev
read:38, InboundMsgAbbrev
readMsgAbbrevs:283, MsgAbbrevJVMConnection
init:213, MsgAbbrevInputStream
dispatch:498, MsgAbbrevJVMConnection
dispatch:330, MuxableSocketT3
run:117, ExecuteThread

2.1.2 CVE-2016-0638(StreamMessageImpl封装)

漏洞原理

  • 利用weblogic.jms.common.StreamMessageImpl类的readExternal方法
  • 当输入数据第一个字节为1时,会对后续数据调用反序列化函数

关键代码

public void readExternal(ObjectInput var1) throws IOException, ClassNotFoundException {
    super.readExternal(var1);
    byte var2 = var1.readByte();
    byte var3 = (byte)(var2 & 127);
    if (var3 >= 1 && var3 <= 3) {
        switch(var3) {
            case 1:
                this.payload = (PayloadStream)PayloadFactoryImpl.createPayload((InputStream)var1);
                BufferInputStream var4 = this.payload.getInputStream();
                ObjectInputStream var5 = new ObjectInputStream(var4);
                this.setBodyWritable(true);
                this.setPropertiesWritable(true);
                try {
                    while(true) {
                        this.writeObject(var5.readObject());

2.1.3 CVE-2016-3510(MarshalledObject利用)

漏洞原理

  • 利用weblogic.corba.utils.MarshalledObject
  • 默认反序列化流程会调用readResolve方法,进而触发反序列化

调用栈

readResolve:58, MarshalledObject
invoke0:-1, NativeMethodAccessorImpl
invoke:39, NativeMethodAccessorImpl
invoke:25, DelegatingMethodAccessorImpl
invoke:597, Method
invokeReadResolve:1061, ObjectStreamClass
readOrdinaryObject:1761, ObjectInputStream
readObject0:1328, ObjectInputStream
readObject:350, ObjectInputStream
readObject:66, InboundMsgAbbrev

2.2 T3 + JRMP协议利用漏洞

2.2.1 CVE-2017-3248(JRMPClient基础利用)

漏洞原理

  • 通过发送实现了UnicastRef的实例,让被攻击的Weblogic向攻击者控制的JRMP服务器发起DGC请求
  • 攻击者服务器返回恶意对象,触发RCE

关键类

  • UnicastRef:RMI远程引用
  • LiveRef:包含目标主机和端口信息
  • RemoteObjectInvocationHandler:封装远程对象调用

调用链

UnicastRef.newCall(RemoteObject, Operation[], int, long)
DGCImpl_Stub.dirty(ObjID[], long, Lease)
DGCClient$EndpointEntry.makeDirtyCall(Set<RefEntry>, long)
DGCClient$EndpointEntry.registerRefs(List<LiveRef>)
DGCClient.registerRefs(Endpoint, List<LiveRef>)
LiveRef.read(ObjectInput, boolean)
UnicastRef.readExternal(ObjectInput)

2.2.2 CVE-2018-2628(JRMPClient变种)

绕过方式

  • JRMPClient2:将接口由Registry改为Activator
  • JRMPClient3:用StreamMessageImpl对RemoteObjectInvocationHandler做封装
  • 直接使用UnicastRef作为payload

2.2.3 CVE-2018-2693(JDK7u21利用链)

漏洞原理

  • 利用JDK自身的类执行代码(不依赖Commons Collections)
  • 关键类:TemplatesImpl + AnnonationInvocationHandler

调用栈

defineTransletClasses:306, TemplatesImpl
getTransletInstance:364, TemplatesImpl
newTransformer:398, TemplatesImpl
getOutputProperties:419, TemplatesImpl
equalsImpl:197, AnnotationInvocationHandler
invoke:59, AnnotationInvocationHandler
equals:-1, $Proxy0
put:475, HashMap
readObject:309, HashSet

2.2.4 CVE-2018-3245(ReferenceWrapper_Stub封装)

特点

  • 使用ReferenceWrapper_Stub类对UnicastRef进行封装

2.2.5 CVE-2018-3191(JNDI注入)

两种利用方式

  1. T3 + JRMP协议:发送恶意实例
  2. T3 + JNDI接口协议:发送恶意类进行加载

关键类

  • JtaTransactionManager:实现serialize接口,readObject会调用context.lookup
  • 攻击者控制JNDI接口地址,返回恶意类

调用栈

getObjectFactoryFromReference:146, NamingManager
getObjectInstance:302, NamingManager
decodeObject:439, RegistryContext
lookup:103, RegistryContext
lookup:185, GenericURLContext
lookup:392, InitialContext
lookup:155, JndiTemplate
lookupUserTransaction:565, JtaTransactionManager
initUserTransactionAndTransactionManager:444, JtaTransactionManager
readObject:1198, JtaTransactionManager
readObject:66, InboundMsgAbbrev

2.3 HTTP + XML协议利用漏洞

2.3.1 CVE-2017-3506(XMLDecoder漏洞)

漏洞原理

  • 利用/wls-wsat/CoordinatorPortType模块
  • XML格式的JavaBean实例数据被解析时执行任意代码

PoC示例

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
      <java version="1.8.0_151" class="java.beans.XMLDecoder">
        <object class="java.lang.ProcessBuilder">
          <array class="java.lang.String" length="3">
            <void index="0"><string>cmd</string></void>
            <void index="1"><string>/c</string></void>
            <void index="2"><string>calc</string></void>
          </array>
          <void method="start"/>
        </object>
      </java>
    </work:WorkContext>
  </soapenv:Header>
  <soapenv:Body/>
</soapenv:Envelope>

调用栈

readObject:201, XMLDecoder
readUTF:111, WorkContextXmlInputAdapter
readEntry:92, WorkContextEntryImpl
receiveRequest:179, WorkContextLocalMap
receiveRequest:163, WorkContextMapImpl
receive:71, WorkContextServerTube
readHeaderOld:107, WorkContextTube
processRequest:43, WorkContextServerTube

2.3.2 CVE-2017-10271(object标签绕过)

绕过方式

  • 使用void标签替换object标签绕过补丁

2.3.3 CVE-2019-2725(新模块利用)

特点

  • 发现新的XML处理模块wls9-async
  • 利用UnitOfWorkChangeSet自身构造函数的反序列化调用过程

三、防护方案

3.1 Weblogic官方防护措施

T3协议防护

  • 黑名单类和包过滤:
    private static final String[] DEFAULT_BLACKLIST_PACKAGES = {
      "org.apache.commons.collections.functors",
      "com.sun.org.apache.xalan.internal.xsltc.trax",
      "javassist",
      "java.rmi.activation",
      "sun.rmi.server",
      "org.jboss.interceptor.builder",
      // 其他包...
    };
    
    private static final String[] DEFAULT_BLACKLIST_CLASSES = {
      "org.codehaus.groovy.runtime.ConvertedClosure",
      "org.codehaus.groovy.runtime.ConversionHandler",
      "org.codehaus.groovy.runtime.MethodClosure",
      "java.rmi.server.UnicastRemoteObject",
      "java.rmi.server.RemoteObjectInvocationHandler",
      // 其他类...
    };
    

HTTP协议防护

  • 在代码中进行XML标签过滤

3.2 网络侧防护建议

  1. T3协议攻击防护

    • 检测T3协议会话特征
    • 使用已知漏洞的类名作为检测特征
    • 如业务不需要,直接阻断T3协议流量
  2. HTTP协议攻击防护

    • 检测特定URL路径(如/_async/wls-wsat
    • 如业务不需要,直接阻断对这些路径的访问
  3. 通用防护措施

    • 及时安装官方补丁
    • 限制Weblogic管理端口的外部访问
    • 监控异常网络连接(特别是出向的JRMP连接)

四、总结与展望

Weblogic反序列化漏洞防护特点:

  • 主要基于黑名单和逐点修复策略
  • 由于Java反序列化机制复杂,仍有新的利用链被不断发现
  • 相比Struts2漏洞危害更大,持续时间更长

当前攻击趋势:

  • 现网流量中大部分是HTTP协议的自动化扫描
  • T3协议利用需要攻击者有公网IP监听,相对较少

防护建议:

  • 持续关注新漏洞信息
  • 采用深度防御策略,结合网络层和应用层防护
  • 对关键系统进行定期漏洞扫描和加固
Weblogic反序列化漏洞深度分析与防护指南 一、Weblogic反序列化漏洞概述 Weblogic反序列化漏洞是一个经典的漏洞系列,根源在于Weblogic(及其他很多Java服务器应用)在通信过程中传输数据对象,涉及到序列化和反序列化操作。如果能找到某个类在反序列化过程中能执行某些奇怪的代码,就有可能通过控制这些代码达到RCE(远程代码执行)的效果。 序列化与反序列化基础 序列化 :将对象转换为字节序列的过程 反序列化 :将字节序列恢复为对象的过程 关键机制 : 实现 Serializable 接口的类支持序列化 可选择实现 writeObject / readObject 和 writeExternal / readExternal 方法 readObject 方法在反序列化时被调用,是漏洞利用的关键点 二、Weblogic历史漏洞分类与详细分析 2.1 T3协议直接利用漏洞 2.1.1 CVE-2015-4582(Commons Collections漏洞) 漏洞原理 : 利用 commons-collections:3.1 库中的 AnnotationInvocationHandler 类 调用链: 关键类 : AnnotationInvocationHandler :触发反序列化入口 LazyMap :实现Map接口,key不存在时通过Transformer生成value InvokerTransformer :执行任意方法调用 ChainedTransformer :链式执行多个Transformer 实际调用栈 : 2.1.2 CVE-2016-0638(StreamMessageImpl封装) 漏洞原理 : 利用 weblogic.jms.common.StreamMessageImpl 类的 readExternal 方法 当输入数据第一个字节为1时,会对后续数据调用反序列化函数 关键代码 : 2.1.3 CVE-2016-3510(MarshalledObject利用) 漏洞原理 : 利用 weblogic.corba.utils.MarshalledObject 类 默认反序列化流程会调用 readResolve 方法,进而触发反序列化 调用栈 : 2.2 T3 + JRMP协议利用漏洞 2.2.1 CVE-2017-3248(JRMPClient基础利用) 漏洞原理 : 通过发送实现了 UnicastRef 的实例,让被攻击的Weblogic向攻击者控制的JRMP服务器发起DGC请求 攻击者服务器返回恶意对象,触发RCE 关键类 : UnicastRef :RMI远程引用 LiveRef :包含目标主机和端口信息 RemoteObjectInvocationHandler :封装远程对象调用 调用链 : 2.2.2 CVE-2018-2628(JRMPClient变种) 绕过方式 : JRMPClient2:将接口由Registry改为Activator JRMPClient3:用StreamMessageImpl对RemoteObjectInvocationHandler做封装 直接使用UnicastRef作为payload 2.2.3 CVE-2018-2693(JDK7u21利用链) 漏洞原理 : 利用JDK自身的类执行代码(不依赖Commons Collections) 关键类: TemplatesImpl + AnnonationInvocationHandler 调用栈 : 2.2.4 CVE-2018-3245(ReferenceWrapper_ Stub封装) 特点 : 使用 ReferenceWrapper_Stub 类对 UnicastRef 进行封装 2.2.5 CVE-2018-3191(JNDI注入) 两种利用方式 : T3 + JRMP协议:发送恶意实例 T3 + JNDI接口协议:发送恶意类进行加载 关键类 : JtaTransactionManager :实现serialize接口,readObject会调用context.lookup 攻击者控制JNDI接口地址,返回恶意类 调用栈 : 2.3 HTTP + XML协议利用漏洞 2.3.1 CVE-2017-3506(XMLDecoder漏洞) 漏洞原理 : 利用 /wls-wsat/CoordinatorPortType 模块 XML格式的JavaBean实例数据被解析时执行任意代码 PoC示例 : 调用栈 : 2.3.2 CVE-2017-10271(object标签绕过) 绕过方式 : 使用 void 标签替换 object 标签绕过补丁 2.3.3 CVE-2019-2725(新模块利用) 特点 : 发现新的XML处理模块 wls9-async 利用 UnitOfWorkChangeSet 自身构造函数的反序列化调用过程 三、防护方案 3.1 Weblogic官方防护措施 T3协议防护 : 黑名单类和包过滤: HTTP协议防护 : 在代码中进行XML标签过滤 3.2 网络侧防护建议 T3协议攻击防护 : 检测T3协议会话特征 使用已知漏洞的类名作为检测特征 如业务不需要,直接阻断T3协议流量 HTTP协议攻击防护 : 检测特定URL路径(如 /_async 和 /wls-wsat ) 如业务不需要,直接阻断对这些路径的访问 通用防护措施 : 及时安装官方补丁 限制Weblogic管理端口的外部访问 监控异常网络连接(特别是出向的JRMP连接) 四、总结与展望 Weblogic反序列化漏洞防护特点: 主要基于黑名单和逐点修复策略 由于Java反序列化机制复杂,仍有新的利用链被不断发现 相比Struts2漏洞危害更大,持续时间更长 当前攻击趋势: 现网流量中大部分是HTTP协议的自动化扫描 T3协议利用需要攻击者有公网IP监听,相对较少 防护建议: 持续关注新漏洞信息 采用深度防御策略,结合网络层和应用层防护 对关键系统进行定期漏洞扫描和加固