序言
环境要求:CommonsCollections: 3.1-3.21 , java版本暂无要求
CommonsCollections6是上一个CC5的改动版。
CC6链中使用的是HashSet
去触发LazyMap的get方法。而在CC5中使用的是BadAttributeValueExpException
分析
1 | package CC6; |
利用链:
1 | Gadget chain: |
在上一节讲过TiedMapEntry
中的getValue()
可以触发get()方法,CC5是用toString()
来调用getValue(),这里我们换一个,用hashcode()
那么就来找找什么地方能调用TiedMapEntry#hashcode()
在HashMap
找到hash
函数,里面调用自己的hashcode()
分析过URLDNS链就应该很眼熟了,如果能控制这个key为TiedMapEntry就能连起来了
正好HashSet#readObject()
完美符合条件
e的结果为s的readObject(),看看它序列化writeObject()
如果我们能控制map中的Key,就能设置s,那么e也就可控了,HashMap#put
的key也可控。
所以我们需要控制传入map的keySet
返回结果来控制变量。
再来看看POC的构造
前半部分依然是和CC5一样
但是后半部分多了一些乍一看挺复杂的步骤
第一个红框处主要是利用反射获取我们的 HashSet
的 map
属性,因为我们要先获取到 map 才能对 map 的 key 进行修改。
第二个红框处则是修改我们 HashMap 中的 key 值为 hashset,在这里利用反射获取了 HashMap 中的 table 属性,table其实就是hashmap的存储底层,将 <Key,Value> 封装在了 Node 对象中,在获取到了 table 中的 key 之后,利用反射修改其为 hashset。
最终的目的只是通过反射修改keySet的返回结果为[TiedMapEntry]而已
简单调试一下
将TiedMapEntry作为e传入hashmap.put()
调用TiedMapEntry#hashcode
调用TiedMapEntry#getValue()
触发LazyMap#get()
后面的事情大家应该都懂。