Oracle cve 2020-14644 分析利用以及回顯思路
0x00 前置知識
1. classloader defineClass
該方法允許將符合class格式的bytes陣列,作為類去載入。該方法返回一個Class物件。
一般情況下,通過defineClass載入的類,不允許同名,否則會報錯,切記
2. java asm& javaassist
既然上面說了,defineClass不允許載入同名類。所以我們需要動態構建class,並生成bytes陣列。在java中一般使用asm或者javaassist通過jvm位元組碼,直接生成一個class。兩種各有優缺點。
- asm語法複雜,需要熟悉jvm底層知識。執行速度快
- 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的程式碼如下
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獲取工具下載