Java安全之CC1-7
Java反序列化漏洞CC1-CC7链的利用流程分析
Apache Commons Collections(CC链)是Java反序列化漏洞中最具代表性的利用链之一,从CC1到CC7链展示了攻击者如何通过精心构造的序列化对象绕过安全防护机制,实现远程代码执行(RCE)。每条CC链都有其特定的入口点、触发链和执行点,这些链利用了Transformer接口及其子类的反射或类加载机制 。本文将详细解析CC1-CC7链的利用流程,帮助安全研究人员和开发人员更好地理解和防御这类漏洞。
一、Transformer接口及其实现类的作用
Transformer接口是Apache Commons Collections中的核心组件,其transform()方法被多个实现类重写,用于在反序列化过程中触发恶意代码执行 :
public interface Transformer {
public Object transform(Object input);
}Transformer接口的主要实现类及其功能如下:
| Transformer类 | 功能描述 | 在CC链中的作用 |
|---|---|---|
| InvokerTransformer | 通过反射动态调用对象的方法 | 执行Runtime.exec()或触发TemplatesImpl类加载 |
| ChainedTransformer | 串联多个Transformer,按顺序执行transform()方法 | 构造Transformer链,传递控制流 |
| ConstantTransformer | 返回固定值,无论输入参数是什么 | 提供Transformer链的初始值,如Runtime.class或TemplatesImpl实例 |
| TiedMapEntry | 包装Map对象,提供get和put方法 | 通过toString()或hashCode()方法触发LazyMap的get()方法 |
| TransformingComparator | 基于Transformer的比较器 | 通过compare()方法触发Transformer链 |
Transformer接口的transform()方法是CC链的核心执行点,攻击者通过构造特定的Transformer链,在反序列化过程中触发恶意代码执行 。不同版本的CC链利用了不同Transformer类的组合,以及不同的触发机制。
二、CC1链的利用流程
CC1链是最早被发现的Commons Collections反序列化漏洞,主要利用了AnnotationInvocationHandler类的反序列化逻辑 :
入口点:AnnotationInvocationHandler.readObject()
触发链:
AnnotationInvocationHandler.readObject() // 反序列化入口
-> map.entrySet() // 触发Map的entrySet方法
-> MapEntry.setValue() // 触发MapEntry的setValue方法
-> parent.checkSetValue(value) // 调用TransformedMap的checkSetValue方法
-> valueTransformer.transform(value) // 触发Transformer链
-> ChainedTransformer.transform() // 串联多个Transformer
-> ConstantTransformer.transform() // 返回固定值Runtime.class
-> InvokerTransformer.transform() // 反射调用Runtime exec方法执行点:InvokerTransformer.transform() → Runtime.exec()
CC1链的构造过程主要包含以下几个关键步骤:
- 创建Transformer链:首先使用ConstantTransformer返回Runtime.class,然后使用两个InvokerTransformer分别获取Runtime的getRuntime()方法和执行exec()方法
- 创建TransformedMap:将Transformer链绑定到Map上,当访问Map的value时会触发Transformer链
- 创建AnnotationInvocationHandler:通过反射构造AnnotationInvocationHandler实例,将其map属性设置为TransformedMap
- 序列化对象:将构造好的AnnotationInvocationHandler对象序列化为字节流
- 触发反序列化:当目标系统反序列化该字节流时,会自动执行Transformer链,最终调用Runtime.exec()执行恶意命令
CC1链的漏洞利用条件包括:使用JDK7或JDK8u65之前的版本,以及存在Apache Commons Collections 3.2.1或更早版本 。
三、CC2链的利用流程
CC2链是针对Commons Collections 4.0版本的漏洞利用链,主要利用了PriorityQueue类的反序列化逻辑和TransformingComparator类 :
入口点:PriorityQueue.readObject()
触发链:
PriorityQueue.readObject() // 反序列化入口
-> heapify() // 堆化操作
-> siftDownUsingComparator() // 堆排序操作
-> comparator.compare() // 调用TransformingComparator的compare方法
-> ChainedTransformer.transform() // 串联多个Transformer
-> ConstantTransformer.transform() // 返回固定值TemplatesImpl实例
-> InvokerTransformer.transform() // 反射调用TemplatesImpl newTransformer方法
-> defineTransletClasses() // 加载恶意类字节码执行点:TemplatesImpl#defineTransletClasses() → defineClass()加载恶意类字节码并执行静态代码块
CC2链的构造过程与CC1链有所不同,主要区别在于触发机制:
- 创建恶意类字节码:编写一个包含恶意代码的Java类,将其编译为字节码
- 创建TemplatesImpl实例:通过反射设置TemplatesImpl的_bytecodes、_name等属性,使其指向恶意类字节码
- 创建TransformingComparator:将InvokerTransformer绑定到TransformingComparator上
- 创建PriorityQueue:使用PriorityQueue作为反序列化入口,设置其comparator为TransformingComparator
- 序列化对象:将构造好的PriorityQueue对象序列化为字节流
- 触发反序列化:当目标系统反序列化该字节流时,会自动执行Transformer链,最终通过defineTransletClasses()加载恶意类并执行静态代码块
CC2链的漏洞利用条件包括:使用JDK8u71或更高版本,以及存在Apache Commons Collections 4.0版本 。
四、CC3链的利用流程
CC3链可以视为CC1链的扩展,主要利用了LazyMap类的反序列化逻辑 :
入口点:AnnotationInvocationHandler.readObject()
触发链:
AnnotationInvocationHandler.readObject() // 反序列化入口
-> map.entrySet() // 触发Map的entrySet方法
-> LazyMap.get() // 触发LazyMap的get方法
-> factory.transform() // 调用Transformer链
-> ChainedTransformer.transform() // 串联多个Transformer
-> ConstantTransformer.transform() // 返回固定值TemplatesImpl实例
-> InvokerTransformer.transform() // 反射调用TemplatesImpl newTransformer方法
-> defineTransletClasses() // 加载恶意类字节码执行点:TemplatesImpl#defineTransletClasses() → defineClass()加载恶意类字节码并执行静态代码块
CC3链的构造过程与CC1链相似,但触发机制不同:
- 创建Transformer链:首先使用ConstantTransformer返回TemplatesImpl实例,然后使用InvokerTransformer反射调用newTransformer()方法
- 创建LazyMap:将Transformer链绑定到LazyMap上,当访问不存在的key时会触发Transformer链
- 创建AnnotationInvocationHandler:通过反射构造AnnotationInvocationHandler实例,将其map属性设置为LazyMap
- 序列化对象:将构造好的AnnotationInvocationHandler对象序列化为字节流
- 触发反序列化:当目标系统反序列化该字节流时,会自动执行Transformer链,最终通过defineTransletClasses()加载恶意类并执行静态代码块
CC3链的漏洞利用条件与CC1链类似,但需要确保LazyMap的触发机制能够正常工作,例如确保访问不存在的key。
五、CC4链的利用流程
CC4链是CC2链的扩展,主要利用了InstanciateTransformer类和TrAXFilter类的构造方法 :
入口点:PriorityQueue.readObject()
触发链:
PriorityQueue.readObject() // 反序列化入口
-> heapify() // 堆化操作
-> siftDownUsingComparator() // 堆排序操作
-> comparator.compare() // 调用TransformingComparator的compare方法
-> ChainedTransformer.transform() // 串联多个Transformer
-> ConstantTransformer.transform() // 返回固定值TrAXFilter.class
-> InstanciateTransformer.transform() // 实例化TrAXFilter对象
-> TrAXFilter.Templates() // 调用Templates构造方法
-> Templates.newTransformer() // 调用newTransformer方法
-> defineTransletClasses() // 加载恶意类字节码执行点:TemplatesImpl#defineTransletClasses() → defineClass()加载恶意类字节码并执行静态代码块
CC4链的构造过程比CC2链更复杂,主要增加了InstanciateTransformer的使用:
- 创建恶意类字节码:编写一个包含恶意代码的Java类,将其编译为字节码
- 创建TemplatesImpl实例:通过反射设置TemplatesImpl的_bytecodes、_name等属性,使其指向恶意类字节码
- 创建InstanciateTransformer:指定目标类为TrAXFilter,并传递TemplatesImpl实例作为参数
- 创建TransformingComparator:将InstanciateTransformer绑定到TransformingComparator上
- 创建PriorityQueue:使用PriorityQueue作为反序列化入口,设置其comparator为TransformingComparator
- 序列化对象:将构造好的PriorityQueue对象序列化为字节流
- 触发反序列化:当目标系统反序列化该字节流时,会自动执行Transformer链,最终通过defineTransletClasses()加载恶意类并执行静态代码块
CC4链的漏洞利用条件与CC2链类似,但需要确保InstanciateTransformer能够正确实例化TrAXFilter对象。
六、CC5链的利用流程
CC5链是针对JDK8u71修复后的漏洞利用链,主要利用了BadAttributeValueExpException类的反序列化逻辑 :
入口点:BadAttributeValueExpException.readObject()
触发链:
BadAttributeValueExpException.readObject() // 反序列化入口
-> ois.readFields() // 读取对象字段
-> valObj.toString() // 调用val对象的toString方法
-> TiedMapEntry.toString() // 触发TiedMapEntry的toString方法
-> TiedMapEntry.getValue() // 触发TiedMapEntry的getValue方法
-> LazyMap.get() // 触发LazyMap的get方法
-> factory.transform() // 调用Transformer链
-> ChainedTransformer.transform() // 串联多个Transformer
-> ConstantTransformer.transform() // 返回固定值Runtime.class
-> InvokerTransformer.transform() // 反射调用Runtime exec方法执行点:InvokerTransformer.transform() → Runtime.exec()
CC5链的构造过程与CC1链相似,但入口点和触发机制不同:
- 创建Transformer链:与CC1链相同,使用ConstantTransformer和两个InvokerTransformer
- 创建LazyMap:将Transformer链绑定到LazyMap上,当访问不存在的key时会触发Transformer链
- 创建TiedMapEntry:将LazyMap和特定key绑定到TiedMapEntry对象上
- 创建BadAttributeValueExpException:通过反射构造BadAttributeValueExpException实例,将其val属性设置为TiedMapEntry对象
- 序列化对象:将构造好的BadAttributeValueExpException对象序列化为字节流
- 触发反序列化:当目标系统反序列化该字节流时,会自动执行Transformer链,最终调用Runtime.exec()执行恶意命令
CC5链的漏洞利用条件包括:使用JDK8u71或更高版本,以及存在Apache Commons Collections 3.2.1或更早版本 。
七、CC6链的利用流程
CC6链是CC5链的变种,主要利用了HashSet类的反序列化逻辑和TiedMapEntry类的hashCode()方法 :
入口点:HashSet.readObject()
触发链:
HashSet.readObject() // 反序列化入口
-> HashMap.put() // 添加元素到HashMap
-> TiedMapEntry.getValue() // 触发TiedMapEntry的getValue方法
-> LazyMap.get() // 触发LazyMap的get方法
-> factory.transform() // 调用Transformer链
-> ChainedTransformer.transform() // 串联多个Transformer
-> ConstantTransformer.transform() // 返回固定值Runtime.class
-> InvokerTransformer.transform() // 反射调用Runtime exec方法执行点:InvokerTransformer.transform() → Runtime.exec()
CC6链的构造过程与CC5链类似,但触发机制不同:
- 创建Transformer链:与CC1链相同,使用ConstantTransformer和两个InvokerTransformer
- 创建LazyMap:将Transformer链绑定到LazyMap上,当访问不存在的key时会触发Transformer链
- 创建TiedMapEntry:将LazyMap和特定key绑定到TiedMapEntry对象上
- 创建HashSet:通过反射构造HashSet实例,将其内部的HashMap设置为包含TiedMapEntry对象
- 序列化对象:将构造好的HashSet对象序列化为字节流
- 触发反序列化:当目标系统反序列化该字节流时,会自动执行Transformer链,最终调用Runtime.exec()执行恶意命令
CC6链的漏洞利用条件与CC5链类似,但需要确保HashSet的反序列化逻辑能够正确触发TiedMapEntry的hashCode()方法。
八、CC7链的利用流程
CC7链是CC6链的变种,主要利用了Hashtable类的反序列化逻辑和AbstractMap的equals()方法 :
入口点:Hashtable.readObject()
触发链:
Hashtable.readObject() // 反序列化入口
-> restitutionPut() // 重建hashtable
-> AbstractMap.equals() // 比较Map对象
-> TiedMapEntry.getValue() // 触发TiedMapEntry的getValue方法
-> LazyMap.get() // 触发LazyMap的get方法
-> factory.transform() // 调用Transformer链
-> ChainedTransformer.transform() // 串联多个Transformer
-> ConstantTransformer.transform() // 返回固定值Runtime.class
-> InvokerTransformer.transform() // 反射调用Runtime exec方法执行点:InvokerTransformer.transform() → Runtime.exec()
CC7链的构造过程与CC6链类似,但触发机制不同:
- 创建Transformer链:与CC1链相同,使用ConstantTransformer和两个InvokerTransformer
- 创建LazyMap:将Transformer链绑定到LazyMap上,当访问不存在的key时会触发Transformer链
- 创建TiedMapEntry:将LazyMap和特定key绑定到TiedMapEntry对象上
- 创建Hashtable:通过反射构造Hashtable实例,将其内部的AbstractMap设置为包含TiedMapEntry对象
- 序列化对象:将构造好的Hashtable对象序列化为字节流
- 触发反序列化:当目标系统反序列化该字节流时,会自动执行Transformer链,最终调用Runtime.exec()执行恶意命令
CC7链的漏洞利用条件与CC6链类似,但需要确保Hashtable的反序列化逻辑能够正确触发AbstractMap的equals()方法。
九、CC链的共同特点和防御建议
尽管CC1-CC7链的利用流程各不相同,但它们都共享一些共同特点:
- 依赖Transformer接口:所有CC链都利用了Transformer接口的transform()方法,通过精心构造的Transformer链实现恶意代码执行
- 利用反射机制:CC链中的InvokerTransformer和InstanciateTransformer都利用了Java反射机制,绕过安全检查
- 利用类加载机制:CC2-CC4链利用了TemplatesImpl类的defineTransletClasses()方法,通过动态加载恶意类字节码实现命令执行
- 利用集合类的反序列化逻辑:CC链的入口点多为集合类(如PriorityQueue、HashSet、Hashtable)的readObject()方法,通过集合类的特定操作触发Transformer链
针对CC链的防御,建议采取以下措施:
- 升级Apache Commons Collections版本:使用4.4或更高版本,这些版本已经修复了CC链相关漏洞
- 限制反序列化入口:避免直接反序列化来自不可信来源的数据,如网络请求、用户输入等
- 使用白名单机制:在反序列化过程中,只允许特定的类和方法被调用,阻止恶意Transformer链的执行
- 使用安全的序列化框架:考虑使用Gson、Jackson等更安全的序列化框架,替代Java原生序列化
- 监控和审计序列化数据:对序列化数据进行监控和审计,及时发现异常的序列化对象
随着Java安全机制的不断改进,CC链的利用难度也在不断增加,但其核心思想——利用Transformer接口的transform()方法触发恶意代码执行——仍然值得安全研究人员深入理解和研究 。
说明:报告内容由通义AI生成,仅供参考。