Spring Security EnableMethodSecurity注解授权绕过(CVE-2025-22223)
字数 1629 2025-08-29 22:41:10
Spring Security EnableMethodSecurity 注解授权绕过漏洞分析 (CVE-2025-22223)
漏洞概述
漏洞编号: CVE-2025-22223
影响版本: Spring Security 6.4.0 - 6.4.3
修复版本: Spring Security 6.4.4
漏洞类型: 授权绕过
漏洞描述: 当使用 @EnableMethodSecurity 注解并在泛型父类、接口或重写方法上使用方法安全注解时,Spring Security 可能无法正确识别子类与父类的方法关系,导致安全注解失效。
受影响的安全注解
以下方法安全注解可能受到影响:
@PreAuthorize("hasRole('ADMIN')")@Secured("ROLE_ADMIN")@PreFilter("filterObject.owner == authentication.name")@PostFilter("filterObject.owner == authentication.name")
漏洞复现环境
- Spring Boot 3.4.3 (默认使用 Spring Security 6.4.3)
- 使用
@EnableMethodSecurity注解 - 包含泛型参数的父类方法上使用安全注解
- 子类继承并实现该方法
漏洞复现步骤
1. 创建Spring Boot入口类
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
2. 创建Spring Web配置类
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((requests) -> requests
.anyRequest().authenticated()
)
.formLogin((form) -> form
.loginPage("/login")
.permitAll()
)
.logout((logout) -> logout.permitAll());
return http.build();
}
}
3. 创建方法安全配置类
@Configuration
@EnableMethodSecurity
public class MethodSecurityConfig {
}
4. 创建方法授权控制服务基类
public abstract class SecureServiceParent<T> {
@Secured({"ROLE_USER", "ROLE_ADMIN"})
public abstract T securedMethod();
}
5. 创建子类实现父类方法
@Service
public class SecureService extends SecureServiceParent<String> {
@Override
public String securedMethod() {
return "Hello from secured method!";
}
}
6. 创建测试控制器
@RestController
public class TestController {
@Autowired
private SecureService secureService;
@GetMapping("/test")
public String test() {
return secureService.securedMethod();
}
}
7. 测试漏洞
访问 /test 接口时,即使未登录也能成功执行 securedMethod 方法,证明安全注解失效。
漏洞原理分析
问题根源
漏洞存在于 org.springframework.security.core.annotation.UniqueSecurityAnnotationScanner 类中,具体在方法注解扫描逻辑上。
关键代码分析
-
方法查找问题:
Method method = targetClass.getDeclaredMethod(methodName, parameterTypes);getDeclaredMethod只能获取当前类声明的方法,无法获取父类方法,特别是当方法包含泛型参数时。 -
注解扫描策略:
findDirectAnnotations(method)使用
DIRECT策略只搜索直接声明在目标元素上的注解,不包括继承的注解。 -
泛型方法参数匹配问题:
- 父类方法签名:
securedMethod() - 子类方法签名:
securedMethod()
虽然看起来相同,但由于泛型擦除和类型参数的实际差异,导致方法匹配失败。
- 父类方法签名:
递归搜索的局限性
虽然 findClosestMethodAnnotations 方法会递归搜索父类和接口的方法,但当方法包含泛型参数时,由于方法签名匹配失败,无法正确找到父类方法及其注解。
漏洞修复方案
官方修复
在 Spring Security 6.4.4 中,官方新增了 findMethod 方法来进行更可靠的方法查找:
private static Method findMethod(Class<?> targetClass, String methodName, Class<?>... parameterTypes) {
// 更完善的方法查找逻辑
}
修复建议
- 升级到 Spring Security 6.4.4 或更高版本
- 如果无法立即升级,可以采取以下临时措施:
- 避免在泛型父类方法上使用安全注解
- 在子类中显式添加安全注解
- 使用接口而非抽象类定义安全方法
漏洞影响评估
受影响场景
- 使用
@EnableMethodSecurity注解 - 存在泛型父类或接口
- 父类或接口方法上使用安全注解
- 子类继承并实现这些方法
不受影响场景
- 不使用泛型的普通方法继承
- 直接在子类方法上使用安全注解
- 不使用
@EnableMethodSecurity注解
参考链接
总结
该漏洞揭示了Spring Security在处理方法安全注解时,特别是涉及泛型继承场景下的缺陷。开发人员应当及时升级到修复版本,并在设计安全控制时注意泛型方法的特殊处理。