最近开始学习java的利用链,也是自己分析的结果,新手如果有错请指正勿喷。
这里对ysoserial的commons1的利用进行分析,从readobject开始,看关键第一步。
get:150, LazyMap (org.apache.commons.collections.map)
invoke:77, AnnotationInvocationHandler (sun.reflect.annotation)
entrySet:-1, $Proxy0 (com.sun.proxy)
readObject:443, AnnotationInvocationHandler (sun.reflect.annotation)
首先执行了AnnotationInvocationHandler.readObject再动态代理执行entrySet时执行了AnnotationInvocationHandler.invoke方法。
然后再调用到了lazymap的get方法。
现在开始执行命令的操作了。从get到达了org.apache.commons.collections.functors.ChainedTransformer#transform函数。
这里对iTransformers进行遍历,他来自于外部的赋值。
再看ysoserial中的transformers数组的内容就理解了,这是生成一个对象的数组赋值给了iTransformers。
第一次循环返回Runtime.class的对象。看下图通过构造函数对ConstantTransformer.iConstant赋值transform返回该对象。
后面的通过不断循环最后调用到了exec方法,InvokerTransformer.iMethodName之类的值都来自最开始构造函数赋值,最后弹出计算器。
JDK1.8 8u71版本以后导致了cc1无法使用,cc2适用于common-collection4-4.0
第一步进入到PriorityQueue.readobject
然后到达了heapify函数。
到这就能理解ysoserial中的这一步就是将size变成2才能够进行下一步。
queue.add(1);
queue.add(1);
最后经过几个函数到达了org.apache.commons.collections4.comparators.TransformingComparator#compare函数,进入了熟悉的transform函数。最后反射执行到com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl的newTransformer
进入到newTransformer然后到函数getTransletInstance。
最后到实例化执行了StubTransletPayload类触发反序列化。
这里还需要进入defineTransletClasses看一下,就能明白将_bytecodes赋值给_class,而_bytecodes就是来自于ysoserial赋值,一个构造函数能够执行命令的类。