Fastjson 1.2.83 安全升级实战:修复 CVE-2022-25845 的 3 种方法与兼容性验证

Fastjson 1.2.83 安全升级实战:修复 CVE-2022-25845 的 3 种方法与兼容性验证

最近在排查项目依赖时发现,Fastjson 这个 Java 生态中使用广泛的 JSON 库又爆出了新的安全漏洞。作为一个长期使用 Fastjson 的开发者,我不得不再次面对这个老问题:如何在保证业务稳定性的前提下,快速有效地修复安全漏洞?本文将分享我在实际项目中处理 CVE-2022-25845 漏洞的完整经验,包括三种不同的修复方案和详细的兼容性验证方法。

1. 漏洞背景与影响评估

CVE-2022-25845 是一个影响 Fastjson 1.2.83 之前所有版本的反序列化漏洞。根据 NVD 的评分,这个漏洞的 CVSS 3.x 基础分数高达 9.8(CRITICAL),属于必须立即处理的高危漏洞。

漏洞本质:攻击者可以通过精心构造的 JSON 数据绕过 Fastjson 的 autoType 关闭限制,实现不受信任数据的反序列化。简单来说,就是攻击者可以远程执行任意代码。

影响范围

  • 所有使用 Fastjson 1.2.82 及以下版本的 Java 应用
  • 特别是那些需要处理外部 JSON 输入的 Web 服务、API 接口等

风险等级评估表

应用场景风险等级说明
处理用户输入的 JSON高危直接面临攻击风险
内部服务间通信中危需评估网络暴露面
仅用于 JSON 生成低危但仍建议升级

提示:即使你的应用不直接处理外部 JSON 输入,依赖链中的其他组件可能在使用 Fastjson,建议进行全面检查。

2. 三种修复方案详解

根据 Fastjson 官方公告和社区实践,我总结了三种可行的修复方案,各有优缺点,开发者可根据实际情况选择。

2.1 方案一:升级至 Fastjson 1.2.83

这是官方推荐的首选方案,也是修复最彻底的方案。

Maven 项目升级步骤

  1. 修改 pom.xml 中的依赖声明:
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency>
  1. 执行依赖更新:
mvn clean install -U

Gradle 项目升级步骤

  1. 修改 build.gradle 中的依赖声明:
dependencies { implementation 'com.alibaba:fastjson:1.2.83' }
  1. 刷新依赖:
gradle --refresh-dependencies

升级注意事项

  • 1.2.83 版本对 autoType 行为有调整,可能影响某些特殊用例
  • 建议先在测试环境验证,特别是涉及复杂对象序列化的场景
  • 检查是否有其他依赖传递引入了旧版本 Fastjson

2.2 方案二:启用 SafeMode

对于暂时无法升级的项目,可以启用 SafeMode 作为临时防护措施。

配置方法

// 应用启动时全局配置 static { ParserConfig.getGlobalInstance().setSafeMode(true); }

SafeMode 的效果

  • 完全禁用 autoType 功能
  • 即使通过 Feature.SupportAutoType 显式开启也无效
  • 从根本上阻断反序列化攻击

适用场景

  • 短期应急方案
  • 确实无法立即升级的特殊情况
  • 确定业务代码不依赖 autoType 功能

注意:SafeMode 是 1.2.68 引入的功能,低于此版本无法使用此方案。

2.3 方案三:迁移至 Fastjson2

Fastjson2 是官方推出的新一代 JSON 库,性能更好且安全性更高。

迁移步骤

  1. 替换依赖:
<dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>2.0.31</version> </dependency>
  1. 修改导入包路径:
    • com.alibaba.fastjson → com.alibaba.fastjson2
    • 注意 API 可能有细微变化

迁移优势

  • 性能提升 20%-50%
  • 更严格的安全设计
  • 长期维护支持

迁移挑战

  • API 不完全兼容
  • 需要全面测试
  • 学习新的最佳实践

三种方案对比表

方案安全性兼容性性能实施难度长期维护
升级至 1.2.83不变
启用 SafeMode不变不推荐
迁移至 Fastjson2最高提升推荐

3. 兼容性验证方案

升级后必须进行全面的兼容性验证,以下是经过实践验证的测试方案。

3.1 基础功能测试集

测试用例设计原则

  • 覆盖所有 JSON 序列化/反序列化场景
  • 特别关注日期、枚举、泛型等特殊类型
  • 验证业务中的自定义序列化逻辑

示例测试代码

public class FastjsonCompatibilityTest { @Test public void testBasicTypes() { // 测试基本类型 assertEquals("123", JSON.parseObject("123", Integer.class).toString()); assertEquals("true", JSON.parseObject("true", Boolean.class).toString()); assertEquals("hello", JSON.parseObject("\"hello\"", String.class)); } @Test public void testDateHandling() { // 测试日期处理 Date now = new Date(); String json = JSON.toJSONString(now); Date parsed = JSON.parseObject(json, Date.class); assertEquals(now.getTime()/1000, parsed.getTime()/1000); } @Test public void testComplexObject() { // 测试复杂对象 User user = new User("test", 30, Arrays.asList("admin", "user")); String json = JSON.toJSONString(user); User parsed = JSON.parseObject(json, User.class); assertEquals(user.getName(), parsed.getName()); assertEquals(user.getRoles(), parsed.getRoles()); } }

3.2 性能基准测试

升级后应该进行性能测试,确保不影响系统吞吐量。

JMH 测试示例

@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.SECONDS) public class FastjsonBenchmark { private static final User testUser = new User("benchmark", 30, Arrays.asList("admin", "user")); @Benchmark public void benchmarkSerialize() { JSON.toJSONString(testUser); } @Benchmark public void benchmarkDeserialize() { String json = JSON.toJSONString(testUser); JSON.parseObject(json, User.class); } }

预期结果

  • 1.2.83 版本性能应与之前版本相当
  • Fastjson2 应有明显性能提升

3.3 自动化回归测试

建议将以下检查加入 CI/CD 流水线:

# 检查是否还有旧版本依赖 mvn dependency:tree | grep fastjson | grep -v 1.2.83 # 运行测试套件 mvn test

4. 生产环境部署策略

即使测试通过,生产环境部署仍需谨慎。以下是推荐的分阶段部署方案:

  1. 金丝雀发布

    • 先在一个节点部署新版本
    • 监控日志是否有序列化异常
    • 逐步扩大部署范围
  2. 监控关键指标

    • JSON 处理成功率
    • 序列化/反序列化耗时
    • 错误日志中的相关异常
  3. 回滚预案

    • 准备旧版本部署包
    • 定义回滚触发条件(如错误率阈值)
    • 测试回滚流程

常见问题处理经验

  • 遇到autoType not support错误:检查是否确实需要 autoType,如必须使用可考虑白名单配置
  • 性能下降:检查是否有自定义序列化器未优化
  • 内存泄漏:监控老年代内存使用情况

在实际项目中,我从 1.2.66 升级到 1.2.83 的过程相对顺利,主要遇到的问题是几个自定义 TypeHandler 需要调整。而迁移到 Fastjson2 的体验则更为复杂,但性能提升确实明显,特别是处理大数组时。