1. 程式人生 > 實用技巧 >Oracle cve 2020-14644 分析利用以及回顯思路

Oracle cve 2020-14644 分析利用以及回顯思路

0x00 前置知識

1. classloader defineClass

該方法允許將符合class格式的bytes陣列,作為類去載入。該方法返回一個Class物件。

一般情況下,通過defineClass載入的類,不允許同名,否則會報錯,切記

2. java asm& javaassist

既然上面說了,defineClass不允許載入同名類。所以我們需要動態構建class,並生成bytes陣列。在java中一般使用asm或者javaassist通過jvm位元組碼,直接生成一個class。兩種各有優缺點。

  1. asm語法複雜,需要熟悉jvm底層知識。執行速度快
  2. javaassist 語法簡單,執行速度慢

在這裡推薦一個asm外掛,可以將class一鍵轉換為asm的java程式碼,並輸出bytes。然後再按需修改class的相關引數

3. java反序列化的transient引數

protected transient Class<? extends Remotable> m_clz;
protected transient MethodHandle m_mhCtor;

transient引數修飾的變數,是不參與反序列化的。最終變數值為null

0x01 cve-2020-14644 漏洞分析

簡單來講,該漏洞在反序列化時通過defineClass直接載入類。下面是待載入的類

下面我們從RemoteConstructor

的newInstance開始分析,斷點設定以及呼叫堆疊如下

newInstance的程式碼如下

    public T newInstance() {
        RemotableSupport support = RemotableSupport.get(this.getClassLoader());
        return support.realize(this);
    }

RemotableSupport可以認為是coherence自定義的Classloader。RemotableSupport中實現了defineClass。下面我們跟入RemotableSupport的realize方法,看一下realize方法都做了什麼

    public <T> T realize(RemoteConstructor<T> constructor) {
        ClassDefinition definition = this.registerIfAbsent(constructor.getDefinition());
        Class<? extends Remotable> clz = definition.getRemotableClass();
        if (clz == null) {
            synchronized(definition) {
                clz = definition.getRemotableClass();
                if (clz == null) {
                    definition.setRemotableClass(this.defineClass(definition));
                }
            }
        }

        Remotable<T> instance = (Remotable)definition.createInstance(constructor.getArguments());
        instance.setRemoteConstructor(constructor);
        return instance;
    }

首先從RemoteConstructor中獲取m_definition,型別為ClassDefinition。隨後呼叫m_definition的getRemotableClass方法。這一句是關鍵。我們去看一下m_definition的getRemotableClass方法

可以很明顯的看到getRemotableClass方法返回的m_clz,是通過transient修飾的。所以在反序列化後,這裡一定返回null。

於是就會走到if條件的另外一個分支,呼叫this.defineClass(definition)去載入類。通過RemotableSupport去根據給定的引數,建立一個類。

RemotableSupport的defineClass方法就很簡單了。從ClassDefinition中獲取類名,類的bytes位元組,呼叫系統的classloader去建立一個類

    protected Class<? extends Remotable> defineClass(ClassDefinition definition) {
        String sBinClassName = definition.getId().getName();
        String sClassName = sBinClassName.replace('/', '.');
        byte[] abClass = definition.getBytes();
        definition.dumpClass(DUMP_REMOTABLE);
        return this.defineClass(sClassName, abClass, 0, abClass.length);
    }

所以payload程式碼如下

在這裡我們只需要通過iiop協議,直接將RemoteConstructor物件傳送給weblogic服務即可

0x02 回顯利用

在cve-2020-2551 回顯利用中,因為classloader的問題,我們需要上傳一個jar包,並區分windows與linux作業系統才可以通過URLClassloader去正確載入上傳的jar包。但是通過該漏洞,我們發現,可以直接寫好類,並轉換為bytes位元組,通過反序列化傳送給weblogic伺服器即可。

至於回顯,無非就是給伺服器安裝一個JNDI例項即可。所以我們需要載入的類的程式碼如下

執行結果如下

目前程式碼已上傳至 https://github.com/potats0/cve_2020_14644

後臺回覆14644獲取工具下載

0x03 參考

  1. https://paper.seebug.org/1281/

歡迎關注 寬位元組安全 公眾號