Spring Security注销后未正确保存空的SecurityContext漏洞CVE-2023-20862

文章目录

  • 0.前言
    • 漏洞
    • [Spring Security介绍](#Spring Security介绍)
  • 1.参考文档
  • 2.基础介绍
  • 3.解决方案
    • [3.1. 升级版本](#3.1. 升级版本)
    • [3.2. 临时替代方案](#3.2. 临时替代方案)
  • [4.Spring Security使用教程简单代码示例](#4.Spring Security使用教程简单代码示例)

0.前言

背景:公司项目扫描到 Spring-security 组件 注销后未正确保存空的SecurityContext CVE-2023-20862

漏洞

高风险 | 2023年4月17日 | CVE-2023-20862

在Spring Security中,5.7.x版本之前的5.7.8版本,5.8.x版本之前的5.8.3版本,以及6.0.x版本之前的6.0.3版本,如果使用序列化版本,注销支持不会正确清理安全上下文。此外,无法将空的安全上下文显式保存到HttpSessionSecurityContextRepository。这种漏洞可能会使用户在注销后仍然保持认证状态。

Spring Security介绍

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是保护基于Spring的应用程序的实际标准。Spring Security提供了一套完整的安全性解决方案,是构建安全性强的企业级应用程序的理想选择。它的模块化和可扩展性使得开发者能够满足各种各样的安全需求,从简单的应用级别的安全到复杂的方法级别的安全,Spring Security都能够提供支持。Spring Security对于所有种类的身份验证机制提供了很好的支持,包括内存存储的用户列表、JDBC基于数据库的认证、LDAP认证、表单认证、CAS等。它不仅支持一大堆认证机制,还支持很多种权限控制的方式,如基于角色的访问控制、访问控制列表(ACL)等。
正因为它是专门搞权限,验证,授权,等安全验证功能,在它上面的漏洞简直层出不穷,防不胜防。所以最近又发布了一个它的漏洞

1.参考文档

  1. CVE 官方网站 https://www.cve.org/CVERecord?id=CVE-2023-20862
  2. spring官方网站 https://spring.io/security/cve-2023-20862
  3. https://docs.spring.io/spring-security/reference/5.8/migration/servlet/session-management.html#_require_explicit_saving_of_securitycontextrepository
  4. https://docs.spring.io/spring-security/reference/servlet/authentication/session-management.html#store-authentication-manually
  5. https://docs.spring.io/spring-security/reference/5.8.3/servlet/authentication/session-management.html#properly-clearing-authentication

2.基础介绍

在Spring Security中,5.7.x版本之前的5.7.8版本5.8.x版本之前的5.8.3版本以及6.0.x版本之前的6.0.3版本,如果使用序列化版本,注销支持不会正确清理安全上下文。此外,无法将空的安全上下文显式保存到HttpSessionSecurityContextRepository。这种漏洞可能会使用户在注销后仍然保持认证状态。

受影响的Spring产品和版本

Spring Security:

6.0.0至6.0.2

5.8.0至5.8.2

5.7.0至5.7.7

3.解决方案

3.1. 升级版本

受影响版本的用户应该应用以下缓解。5.7.x的用户应该升级到5.7.8。5.8.x的用户应该升级到5.8.3。6.0.x的用户应该升级到6.0.3。没有其他必要的步骤。已修复此问题的版本包括:

yaml 复制代码
已修复此问题的版本 Spring Security 版本
5.7.8
5.8.3
6.0.3

3.2. 临时替代方案

  1. 正在使用SecurityContextHolderFilter或requireExplicitSave(true),并且正在使用Spring Security的注销支持与序列化会话(例如Spring Session)和invalidateHttpSession(false)
  2. 通过将一个空的SecurityContext保存到HttpSessionSecurityContextRepository来手动注销用户
  3. 有一个不依赖HttpSession的自定义SecurityContextRepository

4.Spring Security使用教程简单代码示例

  1. 添加Spring Security依赖
xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. 创建Spring Security配置类

创建 SecurityConfig的Java类,这个类需要继承WebSecurityConfigurerAdapter类,并覆盖其configure方法来实现安全配置。也需要配置一个PasswordEncoder bean来处理密码的编码。

java 复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login").permitAll()
                .and()
            .httpBasic();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .passwordEncoder(passwordEncoder())
                .withUser("user").password(passwordEncoder().encode("password")).roles("USER");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

配置指定了所有的请求必须经过身份验证。它还指定一个自定义的登录页面,这个页面对所有用户都是可用的。最后,它配置了一个在内存中的用户存储,包含一个用户名为"user",密码为"password"的用户。

  1. 创建登录页面

在src/main/resources/templates目录下,创建一个名为login.html的文件。此文件的内容可以根据的需求进行定制:

html 复制代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login</title>
</head>
<body>
<form th:action="@{/login}" method="post">
    <div><input type="text" name="username" placeholder="Username"/></div>
    <div><input type="password" name="password" placeholder="Password"/></div>
    <div><input type="submit" value="Sign In"/></div>
</form>
</body>
</html>
  1. 在控制器中使用认证用户信息

在需要使用认证用户信息的地方,可以使用@AuthenticationPrincipal注解来获取当前认证用户:

java 复制代码
@GetMapping("/hello")
public String hello(@AuthenticationPrincipal User user) {
    return "Hello, " + user.getUsername();
}
相关推荐
a程序小傲6 分钟前
国家电网面试被问:FactoryBean与BeanFactory的区别和动态代理生成
java·linux·服务器·spring boot·spring·面试·职场和发展
若鱼191912 分钟前
SpringBoot4.0新特性-Resilience之失败重试
java·spring
哪里不会点哪里.16 分钟前
Spring 核心原理解析:它到底解决了什么问题?
java·后端·spring
梵高的代码色盘1 小时前
互联网大厂Java求职面试实录与技术深度解析
java·spring·缓存·微服务·面试·互联网大厂·技术深度
软件供应链安全指南3 小时前
Forrester发布《2025年应用安全状况报告》,复杂性下的防御体系重构
安全·重构
短剑重铸之日4 小时前
《SpringCloud实用版》完整技术选型地图
java·后端·spring·spring cloud
拽着尾巴的鱼儿5 小时前
Spring定时任务 Scheduled使用
java·后端·spring
Fnetlink15 小时前
零信任架构在移动办公中的应用与安全保障
安全·架构
卓豪终端管理5 小时前
当终端散落四方,安全如何凝聚成墙?
安全
醇氧6 小时前
Spring WebFlux 学习
java·学习·spring