Article directory
0. Preface
Background: The company project scans to CVE-2023-20866: In Spring Session, the session ID will be recorded to the standard output stream
loophole
Medium Risk | April 12, 2023 | CVE-2023-20866
Description
In Spring Session 3.0.0, the session ID is logged to the standard output stream. This vulnerability exposes sensitive information to those who have access to application logs and could be used for session hijacking.
Description
In Spring Session 3.0.0, the session ID is logged to the standard output stream. This vulnerability exposes sensitive information to those who have access to application logs and could be used for session hijacking.
Specifically, the HeaderHttpSessionIdResolver is used and the application is vulnerable.
HeaderHttpSessionIdResolver is not used. then the application is not affected
Affected Spring products and versions
Spring Session 3.0.0
1. Reference documents
CVE official website https://www.cve.org/CVERecord?id=CVE-2023-20866
spring official website https://spring.io/security/cve-2023-20866
2. Basic introduction
CVE-2023-20866: Session IDs are logged to stdout in Spring Session
Medium Risk | April 12, 2023 | CVE-2023-20866
describe
As of Spring Session 3.0.0, the session ID is logged to the standard output stream. This vulnerability exposes sensitive information to those who have access to application logs and could be used for session hijacking.
Specifically, an application is vulnerable when the following conditions are met:
-
HeaderHttpSessionIdResolver is used.
HeaderHttpSessionIdResolver is not used. Then the application is not affected:
Affected Spring products and versions
Spring Session 3.0.0
3. Solutions
3.1. Upgrade version
Users of affected versions should upgrade to Spring Session 3.0.1.
4. HeaderHttpSessionIdResolver analysis
HeaderHttpSessionIdResolver
is HttpSessionIdResolver
an implementation of that is responsible for parsing and writing session IDs from HTTP request and response headers.
The following is HeaderHttpSessionIdResolver
the source code analysis of the main method:
- Constructor
public HeaderHttpSessionIdResolver(String headerName) {
Assert.hasText(headerName, "headerName must not be empty");
this.headerName = headerName;
}
The constructor accepts a string parameter headerName
that represents the session ID key in the HTTP header. This function first checks to see headerName
if is empty and throws an exception if it is empty. Then, headerName
save the to a private field of the class.
resolveSessionIds
method
@Override
public List<String> resolveSessionIds(HttpServletRequest request) {
String sessionId = request.getHeader(this.headerName);
return (sessionId != null ? Collections.singletonList(sessionId) : Collections.emptyList());
}
resolveSessionIds
method to get the session ID from the header of the HTTP request. If a session ID is found, return a list containing only that session ID. If no session ID is found, an empty list is returned.
setSessionId
method
@Override
public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
response.setHeader(this.headerName, sessionId);
}
setSessionId
method writes the session ID into the header of the HTTP response. In this way, the client can obtain the session ID from the header after receiving the response.
expireSession
method
@Override
public void expireSession(HttpServletRequest request, HttpServletResponse response) {
response.setHeader(this.headerName, "");
}
expireSession
method sets the session ID in the header of the HTTP response to an empty string. This way, the client will think the session has expired after receiving the response.
HeaderHttpSessionIdResolver
The implementation of the class is very simple, but it is an important part of session management in Spring Session.
5. Spring Session tutorial
Spring Session provides APIs and implementations for managing user session information in any distributed application. Sessions can be shared across multiple nodes, which is useful for building highly available, scalable applications.
- Add dependencies for Spring Session and corresponding storage types
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
Redis is used here as the storage of session information.
- Configure Spring Session:
@EnableRedisHttpSession
public class HttpSessionConfig {
@Bean
public LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory();
}
}
The annotation here @EnableRedisHttpSession
enables Spring Session support and creates a LettuceConnectionFactory Bean to connect to Redis.
- Using Spring Session:
@Controller
public class HelloController {
@RequestMapping("/setSession")
@ResponseBody
public String setSession(HttpServletRequest request) {
request.getSession().setAttribute("message", "Hello Spring Session");
return "Session Set";
}
@RequestMapping("/getSession")
@ResponseBody
public String getSession(HttpServletRequest request) {
return (String) request.getSession().getAttribute("message");
}
}
setSession()
method stores an attribute into the session and getSession()
method retrieves the attribute from the session.
- Make sure your application is able to connect to the Redis server so that Spring Session will work properly.