CVE-2025-22228 Spring Security 超长密码处理不当漏洞分析
字数 1485 2025-08-29 22:41:01

Spring Security BCryptPasswordEncoder 超长密码处理漏洞(CVE-2025-22228)分析文档

漏洞概述

漏洞编号: CVE-2025-22228
危害等级: 中危
影响组件: org.springframework.security:spring-security-crypto
影响版本: Spring Security < 6.4.4

漏洞描述:
Spring Security 的 BCryptPasswordEncoder 在校验经过 BCrypt 加密后的密码时未对输入密码长度做校验。当攻击者提供的前72个字符与正确密码的前72个字符相同时,系统会错误地认为密码正确,导致攻击者可利用该漏洞绕过身份验证,进行提权或窃取系统敏感信息。

漏洞复现

环境准备

  1. 下载存在漏洞版本的 spring-security-crypto jar 包,例如 5.8.0 版本:

    https://repo.maven.apache.org/maven2/org/springframework/security/spring-security-crypto/5.8.0/spring-security-crypto-5.8.0.jar
    
  2. 创建测试类,避免使用 Spring Boot 完整框架以减少复杂度:

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class Test {
    public static void main(String[] args) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String password = "a".repeat(72) + "b"; // 72个a加1个b
        String encodedPassword = encoder.encode("a".repeat(72) + "c"); // 72个a加1个c
        
        boolean result = encoder.matches(password, encodedPassword);
        System.out.println("验证结果: " + result); // 将输出true
    }
}

复现结果

当输入密码的前72个字符与存储密码的前72个字符相同时,即使后续字符不同,验证结果也会返回true,证明漏洞存在。

BCrypt 算法背景

BCrypt 是一种广泛使用的密码哈希算法,主要特点:

  1. 计算慢:通过调整工作因子(cost)控制哈希计算复杂度,增加暴力破解难度
  2. 抗彩虹表:每次哈希都会生成不同的salt,即使相同密码也会产生不同哈希值
  3. 内置salt:salt存储在哈希结果中,格式为:$2a$[cost]$[22字符salt][31字符hash]

漏洞分析

关键调用链

  1. BCryptPasswordEncoder.matches(CharSequence rawPassword, String encodedPassword)
  2. BCrypt.checkpw(rawPassword.toString(), encodedPassword)
  3. BCrypt.hashpw(password, salt)
  4. BCrypt.ekskey(salt, password)
  5. BCrypt.streamtoword(byte[] data, int[] offp)

漏洞根源

BCrypt.ekskey() 方法中,密码被处理为72字节的块:

  1. streamtoword 方法每次处理4字节,共处理18次(4×18=72)
  2. 当密码长度超过72字节时,超出部分被忽略
  3. 因此只要前72字节匹配,后续内容不影响验证结果

动态调试发现

  1. plen 参数值为16,koffp 参数值为4
  2. 循环处理时,off 值最终为68
  3. streamtoword 方法中完成最后4字节处理,总计72字节

官方修复

Spring Security 6.4.4 版本修复方式:

if (password.length >= 72) {
    throw new IllegalArgumentException("Password too long");
}

在密码长度超过72字节时直接抛出异常,避免截断导致的验证问题。

安全建议

  1. 升级 Spring Security 到 6.4.4 或更高版本
  2. 如果无法立即升级,可自定义 BCryptPasswordEncoder 实现,添加长度检查
  3. 密码策略应限制用户密码长度在合理范围内

扩展思考

此漏洞模式可作为测试用例,适用于所有使用 BCrypt 的场景:

  1. 检查 BCrypt 实现是否对输入密码长度进行验证
  2. 验证超长密码是否会导致意外行为
  3. 如果没有长度检查或异常处理,可能存在类似漏洞

参考

  1. Spring Security 官方文档
  2. BCrypt 算法规范
  3. CVE-2025-22228 漏洞公告
Spring Security BCryptPasswordEncoder 超长密码处理漏洞(CVE-2025-22228)分析文档 漏洞概述 漏洞编号 : CVE-2025-22228 危害等级 : 中危 影响组件 : org.springframework.security:spring-security-crypto 影响版本 : Spring Security < 6.4.4 漏洞描述 : Spring Security 的 BCryptPasswordEncoder 在校验经过 BCrypt 加密后的密码时未对输入密码长度做校验。当攻击者提供的前72个字符与正确密码的前72个字符相同时,系统会错误地认为密码正确,导致攻击者可利用该漏洞绕过身份验证,进行提权或窃取系统敏感信息。 漏洞复现 环境准备 下载存在漏洞版本的 spring-security-crypto jar 包,例如 5.8.0 版本: 创建测试类,避免使用 Spring Boot 完整框架以减少复杂度: 复现结果 当输入密码的前72个字符与存储密码的前72个字符相同时,即使后续字符不同,验证结果也会返回 true ,证明漏洞存在。 BCrypt 算法背景 BCrypt 是一种广泛使用的密码哈希算法,主要特点: 计算慢 :通过调整工作因子(cost)控制哈希计算复杂度,增加暴力破解难度 抗彩虹表 :每次哈希都会生成不同的salt,即使相同密码也会产生不同哈希值 内置salt :salt存储在哈希结果中,格式为: $2a$[cost]$[22字符salt][31字符hash] 漏洞分析 关键调用链 BCryptPasswordEncoder.matches(CharSequence rawPassword, String encodedPassword) BCrypt.checkpw(rawPassword.toString(), encodedPassword) BCrypt.hashpw(password, salt) BCrypt.ekskey(salt, password) BCrypt.streamtoword(byte[] data, int[] offp) 漏洞根源 在 BCrypt.ekskey() 方法中,密码被处理为72字节的块: streamtoword 方法每次处理4字节,共处理18次(4×18=72) 当密码长度超过72字节时,超出部分被忽略 因此只要前72字节匹配,后续内容不影响验证结果 动态调试发现 plen 参数值为16, koffp 参数值为4 循环处理时, off 值最终为68 在 streamtoword 方法中完成最后4字节处理,总计72字节 官方修复 Spring Security 6.4.4 版本修复方式: 在密码长度超过72字节时直接抛出异常,避免截断导致的验证问题。 安全建议 升级 Spring Security 到 6.4.4 或更高版本 如果无法立即升级,可自定义 BCryptPasswordEncoder 实现,添加长度检查 密码策略应限制用户密码长度在合理范围内 扩展思考 此漏洞模式可作为测试用例,适用于所有使用 BCrypt 的场景: 检查 BCrypt 实现是否对输入密码长度进行验证 验证超长密码是否会导致意外行为 如果没有长度检查或异常处理,可能存在类似漏洞 参考 Spring Security 官方文档 BCrypt 算法规范 CVE-2025-22228 漏洞公告