java安全-CC6
Java安全-CC6
环境搭建
1 | jdk1.8u71 |
危险类调用点
这里依旧是 CC1 的危险点
依旧是调用
ChainedTransformer的Transformer方法进而执行Runtime.exec方法
这里,我们从危险利用点分析
一、主要逻辑
1.LazyMap#get

这里依旧用的CC1的 transform 方法
根据逻辑,我们勘测到只有当 map 集合中不包含 key 时,我们会调用 transform 方法
1 | Map lazyMap = LazyMap.decorate(map,chuanTransformer); |
2.TiedMapEntry#hashCode
我们为了调用上一个提供的 get 方法,找到了这里

当调用 hashCode 方法时,会调用类的 getValue 方法

而这个 getValue 方法,会调用 map 集合的 get 方法
我们可以直接将 map 赋值为 LazyMap 类,进而调用其的 get 方法
1 | TiedMapEntry foo = new TiedMapEntry(lazyMap, "aaa"); |
3.HashMap#readObject

这里同时也是反序列化漏洞入口点
我们在反序列化时,会调用被反序列化对象的 readObject 方法,这里进而会调用 hash 方法

而 hash 方法会调用传入值 key 的hashCode 方法
我们给一个 key 赋值为恶意类 TiedMapEntry 类
1 | TiedMapEntry foo = new TiedMapEntry(lazyMap, "aaa"); |
二、额外
1.obj2.put(foo, "bar");

运行这个方法时,会调用 hash 方法,从而会调用我们的恶意链,执行命令
所以为了在反序列化之前不调用恶意链,我们先 put 一个正常无害链,最后通过反射修改为恶意链
1 | Transformer[] chuan0000 = new Transformer[]{new ConstantTransformer(1)}; |
2.LazyMap#get

反序列化时,会调用 get 方法时,我们在当初创建 map 类时,此 key 与 value 已经被加入到 map 中

这样在反序列化的时候,便不会执行 lazyMap 的 put 中的逻辑,因为已经包含
所以我们需要删除,以便逻辑正常
1 | map.remove("aaa"); |
3.调试的坑
在调试的时候,只有一出现断点就会执行命令,这是因为在 IDEA 进行 debug 调试的时候,为了展示对象的集合,会自动调用 toString() 方法,所以在创建 TiedMapEntry 的时候,就自动调用了 getValue() 最终将链子走完,然后弹出计算器。

三、总结
1.链路逻辑
1 | readObject |
common collection
1 | org/apache/commons/collections/keyvalue/TiedMapEntry.java |
2.最终poc
1 | Class r = Runtime.class; |
3.版本限制
| 限制类型 | CC6 的情况 | 备注 |
|---|---|---|
| Commons Collections 3.1 - 3.2.1 | ✅ 可用 | 黄金利用区间 |
| Commons Collections 3.2.2+ | ❌ 不可用 | 默认禁用反序列化,抛异常 |
| Commons Collections 4.0 | ✅ 可用 | 需要修改包名为 commons-collections4 |
| Commons Collections 4.1+ | ❌ 不可用 | 彻底移除了序列化接口 |
| JDK 8u71 之前 | ✅ 可用 | 通杀 |
| JDK 8u71 之后 (包含 JDK 11/17) | ✅ 可用 | 这是 CC6 相比 CC1 的核心优势 |
| JEP 290 过滤器 | ❌ 不可用 | 如果配置了黑名单,任何链都会挂 |