Spring Security does not properly save empty SecurityContext vulnerability CVE-2023-20862 after logout


insert image description here

0. Preface

Background: The company project scanned and found that the empty SecurityContext CVE-2023-20862 was not correctly saved after the Spring-security component was logged out

loophole

High Risk | April 17, 2023 | CVE-2023-20862

In Spring Security, versions 5.7.8 prior to 5.7.x, 5.8.3 prior to 5.8.x, and 6.0.3 prior to 6.0.x, logout support will not be correct if serialized versions are used Clean up the security context. Also, there is no way to explicitly save an empty security context to the HttpSessionSecurityContextRepository.This vulnerability could allow users to remain authenticated after logging out

Introduction to Spring Security

Spring Security is a powerful and highly customizable authentication and access control framework. It is the de facto standard for securing Spring-based applications. Spring Security provides a complete set of security solutions and is an ideal choice for building enterprise-level applications with strong security. Its modularity and extensibility enable developers to meet a variety of security needs, from simple application-level security to complex method-level security, Spring Security can provide support. Spring Security provides good support for all kinds of authentication mechanisms, including memory-stored user lists, JDBC database-based authentication, LDAP authentication, form authentication, CAS, etc. It not only supports a large number of authentication mechanisms, but also supports many ways of permission control, such as role-based access control, access control list (ACL), etc.
Just because it is specialized in authority, verification, authorization, and other security verification functions, there are endless loopholes in it, and it is hard to prevent. So recently released another exploit for it

1. Reference documents

  1. CVE official website https://www.cve.org/CVERecord?id=CVE-2023-20862
  2. spring official website https://spring.io/security/cve-2023-20862
    insert image description here
  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. Basic introduction

In Spring Security, 5.7.x版本prior to 5.7.8版本, 5.8.x版本之前的5.8.3版本, 以及6.0.x版本之前的6.0.3版本, logout support would not properly clean up the security context if the serialized version was used. Also, there is no way to explicitly save an empty security context to HttpSessionSecurityContextRepository. This vulnerability could allow a user to remain authenticated after logging out.

Affected Spring products and versions

Spring Security:
6.0.0 to 6.0.2
5.8.0 to 5.8.2
5.7.0 to 5.7.7

3. Solutions

3.1. Upgrade version

Users of affected versions should apply the following mitigations. 5.7.x users should upgrade to 5.7.8. 5.8.x users should upgrade to 5.8.3. 6.0.x users should upgrade to 6.0.3. No other steps are necessary. Versions that have fixed this issue include:

已修复此问题的版本 Spring Security 版本
5.7.8
5.8.3
6.0.3

3.2. Interim alternatives

  1. Are using SecurityContextHolderFilter or requireExplicitSave(true) and are using Spring Security's logout support with serialized sessions (e.g. Spring Session) and invalidateHttpSession(false)
  2. Manually log out the user by saving an empty SecurityContext to the HttpSessionSecurityContextRepository
  3. Have a custom SecurityContextRepository that doesn't depend on HttpSession

4. Spring Security tutorial simple code example

  1. Add Spring Security dependency
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. Create a Spring Security configuration class

Create a Java class of SecurityConfig, which needs to inherit the WebSecurityConfigurerAdapter class and override its configure method to implement security configuration. A PasswordEncoder bean also needs to be configured to handle encoding of passwords.

@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();
    }
}

The configuration specifies that all requests must be authenticated. It also specifies a custom login page that is available to all users. Finally, it configures an in-memory user store containing a user named "user" and password "password".

  1. Create a login page

In the src/main/resources/templates directory, create a file named login.html. The content of this file can be customized according to your needs:

<!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. Use the authenticated user information in the controller

Where authentication user information needs to be used, the @AuthenticationPrincipal annotation can be used to obtain the current authenticated user:

@GetMapping("/hello")
public String hello(@AuthenticationPrincipal User user) {
    
    
    return "Hello, " + user.getUsername();
}

Guess you like

Origin blog.csdn.net/wangshuai6707/article/details/132543947