还债系列-Java反序列化链条分析补全(2)-CC3
前言
今天我们来分析一下CC3链,这个利用链和CC1链大同小异,区别和CC2链以及CC4链类似,都是InvokerTransformer类被替换成为InstantiateTransformer,废话不多说,我们看看这个链条的分析。
适用范围:
CommonCollections1 :commons-collections:3.1
CommonCollections3 :commons-collections:3.1
分析
更换触发类的原因
我们参考commons-collections:3.1之后的版本3.2.2-rc1,会发现InvokerTransformer类,添加了readObject方法,导致需要指定deserializeProperty,才能正常反序列化InvokerTransformer类,默认情况为false。
链条本体分析
先来看看ysoserial如何构造链条本体:
阅读过前一篇的同学,前几行应该没有问题的,作用也很简单,构造一个ChainedTransformer,把需要transformer的链条进行输入,然后利用ConstTransformer进行包装,让TrAXFilter类能够成功初始化TemplateImpl类。
触发手法
主要在于后面的触发手法,这里我们可以看到使用类HashMap,也使用了lazyMap进行包装,然后再借由InvocationHandler类进行触发,这是链条大致的整体过程。
从构造方面来看,以挖掘链条的思路来看这件事情:
首先我们构造了一个LazyMap,hashMap暂时没什么好看的,lazyMap如果想要输出整体利用链,那他的类方法中必定有一个类,能够调用transformer方法,这个方法为:
这里调用了lazyMap类中的factory属性,并调用了其transformer方法,根据构造函数,需要传入两个参数Map和transformer:
第二个参数会作为属性factoty的值,因此很显然我们transformer需要传入ChainedTransformer,现在问题在于LazyMap的readObject方法,不会直接调用get方法,因而实际上这里是无法触发利用链的:
调用LazyMap.get方法
姑且看看CC3链条的上一层InvokerTransformer,InvokerTransformer是一个接口,根据动态调试不难发现:
实际上是AnnotationInvocationHandler类,我们来看看源代码,由于整体是反序列化链条,很自然就会看向该类的readObject方法:
仔细一看没什么特别的,只是会传入一个var4进行迭代而已,实际上原因在于ysoserial的构造上:
之前ysoserial进行了构造代理的操作,将Map类的相关函数,代理给了AnnotationInvocationHandler,因此当我们调用Map类的,任意方法时都会移交给AnnotationInvocationHandler.invoke方法进行处理,LazyMap装饰Map类,LazyMap也是调用Map中的一些方法,也可以被AnnotationInvocationHandler代理。
来看看AnnotationInvocationHandler.invoke:
这里会默认调用memberValues属性的get方法,在readObject中该属性被恢复了出来,意味着我们构造时该属性是可控的,这里只需要传入LazyMap即可。
后面的触发过程自然就是简单总结就是:
LazyMap.get() ->
ChainedTransformer.transformer() ->
InstantiateTransformer.transformer(TrAXFilter) ->
TrAXFilter.getConstructor(TemplateImpl.class) ->
TrAxFilter.newInstance() ->
TemplateImpl.newTransformer(byte[] EvilByte ->
definedClass(EvilByte)
从而完成本次利用链的反序列化