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/

歡迎關注 寬字節安全 公眾號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM