SpringShell is a new Spring Framework Remote Code Execution (RCE), aka CVE-2022-22965, security vulnerability. Essentially all versions of the Spring Framework, including 5.3.0 to 5.3.17, 5.2.0 to 5.2.19, and older, unsupported versions are vulnerable.
Check if your Spring application is Vulnerable?
- If you are using JDK 9 or higher.
- If you are using Apache Tomcat as the Servlet container.
- If your application build is packaged as a traditional WAR.
- If you are using spring-webmvc or spring-webflux dependency.
Experts are saying even if you are not doing any of the above you may still be vulnerable. The Spring community admits, “the nature of the vulnerability is more general, and there may be other ways to exploit it.”
Vulnerability Fixes
Spring Framework 5.3.18 and 5.2.20 have already been released.
If you are using Spring Boot directly – upgrade to version 2.6.6
For maven users
<properties>
<spring-framework.version>5.3.18</spring-framework.version>
</properties>
For gradle users
ext['spring-framework.version'] = '5.3.18'
If you want to handle it without upgrading, a fail-safe workaround by Spring official blog
Applications could extend RequestMappingHandlerAdapter to update the WebDataBinder at the end after all other initialization. In order to do that, a Spring Boot application can declare a WebMvcRegistrations bean (Spring MVC) or a WebFluxRegistrations bean (Spring WebFlux).
For Spring MVC(and similar in WebFlux):
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.InitBinderDataBinderFactory;
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory;
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(CarApp.class, args);
}
@Bean
public WebMvcRegistrations mvcRegistrations() {
return new WebMvcRegistrations() {
@Override
public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
return new ExtendedRequestMappingHandlerAdapter();
}
};
}
private static class ExtendedRequestMappingHandlerAdapter extends RequestMappingHandlerAdapter {
@Override
protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> methods) {
return new ServletRequestDataBinderFactory(methods, getWebBindingInitializer()) {
@Override
protected ServletRequestDataBinder createBinderInstance(
Object target, String name, NativeWebRequest request) throws Exception {
ServletRequestDataBinder binder = super.createBinderInstance(target, name, request);
String[] fields = binder.getDisallowedFields();
List<String> fieldList = new ArrayList<>(fields != null ? Arrays.asList(fields) : Collections.emptyList());
fieldList.addAll(Arrays.asList("class.*", "Class.*", "*.class.*", "*.Class.*"));
binder.setDisallowedFields(fieldList.toArray(new String[] {}));
return binder;
}
};
}
}
}