关于CC链1中的一些问题分析
字数 1915 2025-08-29 08:30:12
Commons Collections 1反序列化链(CC1)详细分析
0x00 前言
CC1链是Apache Commons Collections库中的一个著名反序列化漏洞利用链,本文面向刚开始分析CC1链的学习者,详细解释链中的关键点和常见疑惑。
0x01 完整EXP
由于篇幅限制,EXP代码以图示形式展示,读者也可参考其他分析文章获取完整利用代码。
0x02 HashMap.put()的关键作用
1. 为何需要调用hashmap.put()
在CC1链中,反序列化过程从AnnotationInvocationHandler的readObject方法开始,目标是调用其中的memberValue.setValue()方法。但这个方法位于for-each循环中:
- 通过反射创建
AnnotationInvocationHandler对象时需要传入一个Map - 这个Map对应
readObject方法中的memberValues变量 - 如果
memberValues为空,for循环会直接跳过不执行内部代码 - 因此必须调用
hashmap.put()向Map中添加数据才能进入循环体
2. 为何第一个键必须是"value"
关键原因在于AnnotationInvocationHandler的处理逻辑:
- 构造
AnnotationInvocationHandler时第一个参数通常设为Target.class注解 Target.class注解包含value键,使得memberTypes.get(name)能获取到非空值name来自memberValue.getKey(),即Map的键- 因此Map的键必须与注解中定义的键匹配(如
value)
替代方案:也可以使用其他包含键的注解如Repeatable.class或Retention.class
0x03 AbstractInputCheckedMapDecorator中的setValue()
1. TransformedMap为何会调用父类的setValue
关键继承关系:
TransformedMap → AbstractInputCheckedMapDecorator → AbstractMapDecorator
关键点:
TransformedMap本身没有setValue()方法- 调用时会向上查找父类
AbstractInputCheckedMapDecorator中的方法 - 该类重写了for-each循环的底层逻辑
- 通过
MapEntry类生成Map条目,而MapEntry中包含setValue方法
2. parent如何被控制为我们想要的Map类型
调用链分析:
TransformedMap找不到setValue方法,转向父类查找- 在
entrySet()方法中,将this(即TransformedMap实例)传递给EntrySet构造方法 EntrySet构造方法中的parent参数就是传入的TransformedMap- 最终
setValue操作实际上是通过TransformedMap执行的
调试建议:通过调试观察parent和this的变化情况可以更直观理解这个过程。
0x04 关键类与方法总结
| 类/方法 | 作用 |
|---|---|
AnnotationInvocationHandler.readObject() |
反序列化入口点 |
HashMap.put() |
确保进入for循环体 |
AbstractInputCheckedMapDecorator.setValue() |
实际触发点 |
TransformedMap |
恶意数据载体 |
Target.class |
提供必要的注解键 |
0x05 调试技巧
- 重点关注
memberValues和memberTypes的变化 - 观察
setValue调用栈,理解方法查找过程 - 注意
parent和this在调用链中的传递
0x06 常见问题解答
Q: 为什么必须使用Target.class作为注解参数?
A: 不是必须使用Target.class,但必须使用包含相应键(如value)的注解类。
Q: 为什么TransformedMap没有setValue却能调用?
A: 通过父类AbstractInputCheckedMapDecorator的继承和方法重写机制实现。
Q: 如何确认链的每个环节都正确连接?
A: 通过调试逐步跟踪,确保每个环节的参数传递和方法调用符合预期。