apache-commons-collections3反序列化链分析
调试环境
JDK7+commons-collections-3.1.jar
apache-commons-collections3反序列化链其实利用的地方跟ACC1链一样,只是构造payload的方法有所不同罢了,apache-commons-collections3反序列化链的payload构造利用到了apache-commons-collections1、apache-commons-collections3反序列化链构造的知识点
下面根据ysoserial工具生成apache-commons-collections3反序列化链payload的代码进行分析,没了解过ACC1和ACC2链的可以先去把这两天链跟了,再来看这条链会比较好
漏洞分析
看到CommonsCollections3.getObject
方法,这个方法调用Gadgets.createTemplatesImpl
方法动态生成恶意的TemplatesImpl类,这里跟CommonsCollections2链是一样的,不了解的可以参考这篇文章,这里不再赘述
然后实例化一个ChainedTransformer,分析过ACC1链的知道ChainedTransformer存在一组反射调用(具体可看ACC1链),实例化时里面的参数为Transformer数组,数组里面是一个ConstantTransformer对象,后面再反射赋值 iTransformers 为transformers变量
这里去掉实例化ChainedTransformer时传入的参数,并且一开始就把transformers变量通过构造方法赋值给iTransformers也可以执行命令成功,那么这个传入的参数意义何在?下面是网上师傅的一个解释
后面反射赋值还是有意义的。如果在一开始就把transformers这个数组放入transformerChain,就会导致构造链的时候(而不是(调用readObject的时候)自己弹自己计算机
ACC3链的构造是基于LazyMap攻击链的,getObject方法中实例化了HashMap之后实例化LazyMap对象,并在实例化LazyMap对象的时候传入HashMap和ChainedTransformer对象,这个分析过ACC1 LazyMap攻击链的应该不陌生,这时候只要调用到LazyMap.get方法就可以反射调用到一组方法
当我们调用到LazyMap.get
方法的时候会调用怎样的一组方法呢?这就要看赋值给ChainedTransformer对象的iTransformers属性的Transformer数组是怎么构造的了,payload构造中涉及到了TrAXFilter类和InstantiateTransformer类,下面一个个看
ACC1链的时候分析过,ConstantTransformer.transform
方法返回的就是实例化ConstantTransformer时传入的值,ACC1中传入的是Runtime.class,这里传入的是TrAXFilter.class
看一下TrAXFilter类,这个类的构造方法执行了templates.newTransformer()
方法,回顾ACC2链不就是通过newTransformer方法实例化恶意类时调用到静态代码块而执行系统命令的吗?那么这里只要让templates为动态生成的恶意类即可,这是transformers要实现的第一个点
再看InstantiateTransformer类的transform方法,transform方法可以调用到input参数类的构造方法,那么只要构造input参数为TrAXFilter类即可调用TrAXFilter类的构造方法,这是transformers要实现的第二个点
如下构造Transformer数组就可以满足第一个点和第二个点,仔细分析分析应该不难理解
没分析过ysoserial生成ACC1链payload的过程,下面这初略的讲解应该很难听懂,可以先去跟一下ysoserial生成ACC1链payload的过程
只需要调用到LazyMap的get方法就可以完成这条链的构造了,这里利用的是ysoserial生成ACC2链的方法,通过生成LazyMap的动态代理对象(这个代理对象的处理器为AnnotationInvocationHandler对象,代理的接口为Map接口,当调用到Map接口中的方法时,就交给AnnotationInvocationHandler.invoke
处理)
ysoserial最后构造的payload是AnnotationInvocationHandler这个对象的序列化数据,在反序列化AnnotationInvocationHandler对象的时候,会调用到AnnotationInvocationHandler.readObject
方法,readObject方法会调用到this.memberValues.entrySet
方法,这里的this.memberValues
就是LazyMap的动态代理对象,而entrySet又是Map接口的方法,那么这时候就会交给AnnotationInvocationHandler.invoke
处理,invoke方法会调用到this.memberValues.get
方法,这里的this.memberValues
为LazyMap对象(跟前面的不同,具体可以跟进getObject方法中的createMemoitizedProxy方法和createMemoizedInvocationHandler方法),这时候调用到LazyMap.get
方法,实现反序列化构造,到这里就完成了ACC3这条链的构造了。
总结
跟过ACC1链、ACC2链基础和ysoserial生成ACC1链、ACC2链payload的应该很容易看懂这条ACC3链,用的都是ACC1和ACC2链的知识点