Updates:

  • [15:40 BST] Spring Boot 2.6.6 is available.
  • [14:38 BST] Spring Boot 2.5.12 is available.
  • [14:00 BST] CVE-2022-22965 is published.
  • [13:03 BST] Added section “Misconceptions”.
  • [12:34 BST] Added section “Am I Impacted”.
  • [12:11 BST] Fix minor issue in the workaround for adding disallowedFields .
  • [11:59 BST] Spring Framework versions 5.3.18 and 5.2.20 , which address the vulnerability, are now available. The release process for Spring Boot is in progress.

Overview

I would like to announce an RCE vulnerability in the Spring Framework that was leaked out ahead of CVE publication. The issue was first reported to VMware late on Tuesday evening, close to Midnight, GMT time by codeplutos, meizjm3i of AntGroup FG. On Wednesday we worked through investigation, analysis, identifying a fix, testing, while aiming for emergency releases on Thursday. In the mean time, also on Wednesday, details were leaked in full detail online, which is why we are providing this update ahead of the releases and the CVE report.

Vulnerability

The vulnerability impacts Spring MVC and Spring WebFlux applications running on JDK 9+. The specific exploit requires the application to run on Tomcat as a WAR deployment. If the application is deployed as a Spring Boot executable jar, i.e. the default, it is not vulnerable to the exploit. However, the nature of the vulnerability is more general, and there may be other ways to exploit it.

Am I Impacted?

These are the requirements for the specific scenario from the report:

  • JDK 9 or higher
  • Apache Tomcat as the Servlet container
  • Packaged as a traditional WAR (in contrast to a Spring Boot executable jar)
  • spring-webmvc or spring-webflux dependency
  • Spring Framework versions 5.3.0 to 5.3.17, 5.2.0 to 5.2.19, and older versions

However, the nature of the vulnerability is more general, and there may be other ways to exploit it that have not been reported yet.

Status

  • Spring Framework 5.3.18 and 5.2.20, which contain the fixes, have been released
  • Spring Boot 2.6.6 and 2.5.12 that depend on Spring Framework 5.3.18 have been released.
  • CVE-2022-22965 has been published

Suggested Workarounds

NOTE: If you’re able to upgrade to Spring Framework 5.3.18 and 5.2.20 , you do not need this section.

The leaked reports recommend setting disallowedFields on WebDataBinder through an @ControllerAdvice :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@ControllerAdvice
@Order(Ordered.LOWEST_PRECEDENCE)
public class BinderControllerAdvice {

    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
         String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
         dataBinder.setDisallowedFields(denylist);
    }

}

This works generally, but as a centrally applied workaround fix, may leave some loopholes, in particular if a controller sets disallowedFields locally through its own @InitBinder method, which overrides the global setting.

To apply the workaround in a more fail-safe way, 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 example in Spring MVC (and similar in WebFlux):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package car.app;

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;
                }
            };
        }
    }
}

For Spring MVC without Spring Boot, an application can switch from @EnableWebMvc to extending DelegatingWebMvcConfiguration directly as described in Advanced Config section of the documentation, then overriding the createRequestMappingHandlerAdapter method.

Misconceptions

There was speculation surrounding the commit to deprecate SerializationUtils . This class has only one usage within the framework and is not exposed to external input. The deprecation is unrelated to this vulnerability.

There was confusion with a CVE for Spring Cloud Function which was released just before the report for this vulnerability. It is also unrelated.

Further Updates

When the releases are ready, we will post another blog on this site, to announce their availability. So please continue to watch https://spring.io/blog. We may also update this blog post, if there are any corrections to be made, and in that case we’ll clearly call those out at the top.

Reference https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement