apache-commons-collections6反序列化链分析

apache-commons-collections6反序列化链分析

apache-commons-collections6反序列化链利用的也是通过TiedMapEntry.getValue方法调用一系列的transform方法执行系统命令的,下面就分析分析这条链

复现环境

JDK7+CommonsCollections1

漏洞分析

看到CommonsCollections6类的getObject方法,前面是很熟悉的Transformer数组构造,数组构造和ACC5也是一样的,这里直接在实例化ChainedTransformer对象的时候把Transformer数组作为参数传入了,而不是通过反射传入,不过问题都不大
image-20211202170054941
然后实例化HashMap、LazyMap对象,并把这两个对象作为参数实例化TiedMapEntry对象,这里也很熟悉,经过这些实例化操作,TiedMapEntry对象的this.map值为LazyMap对象,
image-20211202170240999
这时候只要调用到TiedMapEntry.getValue方法就可以调用一系列的transform方法执行系统命令了,至此,前面的都和ACC5链一样,那么下面看看怎么构造才能调用到TiedMapEntry.getValue方法
image-20211202170343158
实例化一个容量为1的HashSet对象,并把foo字符串添加进去占位,再通过反射获取HashSet对象的map属性的Field对象,并赋值到f变量,然后通过get方法获取到属性值并赋值到innimpl变量
image-20211202171941180
HashSet对象的map属性为一个HashMap对象,所以innimpl变量就是一个HashMap对象
image-20211202170657886
之后反射获取HashMap的table属性的Field对象,并赋值给f2变量
image-20211202171535849
HashMap的table属性字段为Node类,Node是HashMap的一个内部类
image-20211202171605101
再反射获取Entry属性赋值到node变量,也就是node变量就是HashMap$Node内部类
image-20211202172714716
反射获取HashMap$Node内部类的key字段的Field对象,并把这个字段的key属性赋值为TiedMapEntry对象,最后返回的是HashSet对象
image-20211202172858042
上面的一系列操作就是把HashSet对象中的map属性对象(这属性是一个HashMap对象)里面的Node内部类的key属性赋值为TiedMapEntry对象(当HashSet对象中的map属性为HashMap对象时,HashSet.add方法中添加的元素就是存储在HashMap对象的key属性中的)

跟进HashSet.readObject方法,先调用默认的defaultReadObject方法保证反序列化操作的正常进行,然后实例化一个HashMap对象赋值给map变量,再for循环用map.put方法对map变量赋值。
image-20211202173539328
跟进put方法,注意put方法的参数e是内部Node类的key属性,也就是TiedMapEntry对象,put方法调用hash方法对TiedMapEntry对象进行处理。这里为什么参数e是内部Node类的key属性呢?跟进一下HashSet.writeObject方法中的,得知在调用HashSet.writeObject方法序列化对象的时候通过s.writeObject写入的就是TiedMapEntry对象,那么反序列化时s.readObject当然读取到的也就是TiedMapEntry对象
image-20211202173802744
跟进hash方法,其调用k.hashCode方法,也就是调用TiedMapEntry.hashCode方法
image-20211202174242507
跟进TiedMapEntry.hashCode方法,其调用getValue方法。自此,就调用到TiedMapEntry.getValue方法了,进而调用一系列transform方法执行系统命令
image-20211202183332857

总结

在这条链中要注意的地方有两个

当HashSet的map属性为HashMap对象时,HashSet.put方法添加的元素是存储在HashSet的map属性对象的内部Node类的key属性中的,所以在HashSet.readObject方法中,map.put的参数e为key属性,也就是构造payload时指定的TiedMapEntry对象

HashSet对象的map属性是transient修饰符修饰的,但是HashSet对象的writeObject方法和readObject方法手工读取和写入了map属性,所以可以成功序列化和反序列化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值