还债系列-Java反序列化链条分析补全(2)-CC3

还债系列-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。

InvokerTransformer3.2.2-rc1

还债系列-Java反序列化链条分析补全(2)-CC3

链条本体分析

先来看看ysoserial如何构造链条本体:

还债系列-Java反序列化链条分析补全(2)-CC3

阅读过前一篇的同学,前几行应该没有问题的,作用也很简单,构造一个ChainedTransformer,把需要transformer的链条进行输入,然后利用ConstTransformer进行包装,让TrAXFilter类能够成功初始化TemplateImpl类。

触发手法

主要在于后面的触发手法,这里我们可以看到使用类HashMap,也使用了lazyMap进行包装,然后再借由InvocationHandler类进行触发,这是链条大致的整体过程。

从构造方面来看,以挖掘链条的思路来看这件事情:
首先我们构造了一个LazyMap,hashMap暂时没什么好看的,lazyMap如果想要输出整体利用链,那他的类方法中必定有一个类,能够调用transformer方法,这个方法为:
还债系列-Java反序列化链条分析补全(2)-CC3
这里调用了lazyMap类中的factory属性,并调用了其transformer方法,根据构造函数,需要传入两个参数Map和transformer:

还债系列-Java反序列化链条分析补全(2)-CC3

第二个参数会作为属性factoty的值,因此很显然我们transformer需要传入ChainedTransformer,现在问题在于LazyMap的readObject方法,不会直接调用get方法,因而实际上这里是无法触发利用链的:
还债系列-Java反序列化链条分析补全(2)-CC3

调用LazyMap.get方法

姑且看看CC3链条的上一层InvokerTransformer,InvokerTransformer是一个接口,根据动态调试不难发现:
还债系列-Java反序列化链条分析补全(2)-CC3
实际上是AnnotationInvocationHandler类,我们来看看源代码,由于整体是反序列化链条,很自然就会看向该类的readObject方法:

还债系列-Java反序列化链条分析补全(2)-CC3

仔细一看没什么特别的,只是会传入一个var4进行迭代而已,实际上原因在于ysoserial的构造上:

还债系列-Java反序列化链条分析补全(2)-CC3

之前ysoserial进行了构造代理的操作,将Map类的相关函数,代理给了AnnotationInvocationHandler,因此当我们调用Map类的,任意方法时都会移交给AnnotationInvocationHandler.invoke方法进行处理,LazyMap装饰Map类,LazyMap也是调用Map中的一些方法,也可以被AnnotationInvocationHandler代理。

来看看AnnotationInvocationHandler.invoke:
还债系列-Java反序列化链条分析补全(2)-CC3
这里会默认调用memberValues属性的get方法,在readObject中该属性被恢复了出来,意味着我们构造时该属性是可控的,这里只需要传入LazyMap即可。

后面的触发过程自然就是简单总结就是:


LazyMap.get() ->
ChainedTransformer.transformer() ->
InstantiateTransformer.transformer(TrAXFilter) ->
TrAXFilter.getConstructor(TemplateImpl.class) ->
TrAxFilter.newInstance() ->
TemplateImpl.newTransformer(byte[] EvilByte ->
definedClass(EvilByte)

从而完成本次利用链的反序列化

参考文章

初始JavaWeb安全(3)
五分钟彻底理解Java Proxy原理

赞 (0)

评论区

评论一下~


40+47=?

暂无评论,要不来一发?

回到顶部