关于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链中,反序列化过程从AnnotationInvocationHandlerreadObject方法开始,目标是调用其中的memberValue.setValue()方法。但这个方法位于for-each循环中:

  • 通过反射创建AnnotationInvocationHandler对象时需要传入一个Map
  • 这个Map对应readObject方法中的memberValues变量
  • 如果memberValues为空,for循环会直接跳过不执行内部代码
  • 因此必须调用hashmap.put()向Map中添加数据才能进入循环体

2. 为何第一个键必须是"value"

关键原因在于AnnotationInvocationHandler的处理逻辑:

  1. 构造AnnotationInvocationHandler时第一个参数通常设为Target.class注解
  2. Target.class注解包含value键,使得memberTypes.get(name)能获取到非空值
  3. name来自memberValue.getKey(),即Map的键
  4. 因此Map的键必须与注解中定义的键匹配(如value

替代方案:也可以使用其他包含键的注解如Repeatable.classRetention.class

0x03 AbstractInputCheckedMapDecorator中的setValue()

1. TransformedMap为何会调用父类的setValue

关键继承关系:

TransformedMap → AbstractInputCheckedMapDecorator → AbstractMapDecorator

关键点:

  • TransformedMap本身没有setValue()方法
  • 调用时会向上查找父类AbstractInputCheckedMapDecorator中的方法
  • 该类重写了for-each循环的底层逻辑
  • 通过MapEntry类生成Map条目,而MapEntry中包含setValue方法

2. parent如何被控制为我们想要的Map类型

调用链分析:

  1. TransformedMap找不到setValue方法,转向父类查找
  2. entrySet()方法中,将this(即TransformedMap实例)传递给EntrySet构造方法
  3. EntrySet构造方法中的parent参数就是传入的TransformedMap
  4. 最终setValue操作实际上是通过TransformedMap执行的

调试建议:通过调试观察parentthis的变化情况可以更直观理解这个过程。

0x04 关键类与方法总结

类/方法 作用
AnnotationInvocationHandler.readObject() 反序列化入口点
HashMap.put() 确保进入for循环体
AbstractInputCheckedMapDecorator.setValue() 实际触发点
TransformedMap 恶意数据载体
Target.class 提供必要的注解键

0x05 调试技巧

  1. 重点关注memberValuesmemberTypes的变化
  2. 观察setValue调用栈,理解方法查找过程
  3. 注意parentthis在调用链中的传递

0x06 常见问题解答

Q: 为什么必须使用Target.class作为注解参数?
A: 不是必须使用Target.class,但必须使用包含相应键(如value)的注解类。

Q: 为什么TransformedMap没有setValue却能调用?
A: 通过父类AbstractInputCheckedMapDecorator的继承和方法重写机制实现。

Q: 如何确认链的每个环节都正确连接?
A: 通过调试逐步跟踪,确保每个环节的参数传递和方法调用符合预期。

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 本身没有 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: 通过调试逐步跟踪,确保每个环节的参数传递和方法调用符合预期。