Lucene search

K
springRossen StoyanchevSPRING:DA8F6AA20460EB2D550732A7F74584F6
HistoryMar 31, 2022 - 10:27 a.m.

Spring Framework RCE, Early Announcement

2022-03-3110:27:00
Rossen Stoyanchev
spring.io
113

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

7.5 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P

Updates

  • [04-13] "Data Binding Rules Vulnerability CVE-2022-22968" follow-up blog post published, related to the "disallowedFields" from the Suggested Workarounds
  • [04-08] Snyk announces an additional attack vector for Glassfish and Payara. See also related Payara, upcoming release announcement
  • [04-04] Updated Am I Impacted with improved description for deployment requirements
  • [04-01] Updated Am I Impacted with additional notes
  • [04-01] Updated Suggested Workarounds section for Apache Tomcat upgrades and Java 8 downgrades
  • [04-01] "Mitigation Alternative" follow-up blog post published, announcing Apache Tomcat releases versions10.0.20,9.0.62, and8.5.78 that close the attack vector on Tomcat’s side
  • [03-31] Spring Boot 2.6.6 is available
  • [03-31] Spring Boot 2.5.12 is available
  • [03-31] CVE-2022-22965 is published
  • [03-31] Added section "Misconceptions"
  • [03-31] Added section "Am I Impacted"
  • [03-31] Fix minor issue in the workaround for adding disallowedFields
  • [03-31] Spring Framework5.3.18and5.2.20 are available

Table of Contents

  • Overview
  • Vulnerability
  • Am I Impacted
  • Status
  • Suggested Workarounds
  • Misconceptions

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 be packaged and deployed as a traditional WAR on a Servlet container. 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:

Additional notes:

  • The vulnerability involves ClassLoader access and depends on the actual Servlet Container in use. Tomcat 10.0.19, 9.0.61, 8.5.77, and earlier versions are known to be vulnerable. Payara and Glassfish are also known to be vulnerable. Other Servlet containers may also be vulnerable.
  • The issue relates to data binding used to populate an object from request parameters (either query parameters or form data). Data binding is used for controller method parameters that are annotated with @ModelAttribute or optionally without it, and without any other Spring Web annotation.
  • The issues does not relate to @RequestBody controller method parameters (e.g. JSON deserialization). However, such methods may still be vulnerable if they have another method parameter populated via data binding from query parameters.

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.
  • Apache Tomcat has released versions 10.0.20, 9.0.62, and 8.5.78 which close the attack vector on Tomcat’s side, see Spring Framework RCE, Mitigation Alternative.

Suggested Workarounds

The preferred response is to update to Spring Framework 5.3.18 and5.2.20 or greater. If you have done this, then no workarounds are necessary. However, some may be in a position where upgrading is not possible to do quickly. For that reason, we have provided some workarounds below.

  • Upgrading Tomcat
  • Downgrading to Java 8
  • Disallowed Fields

Please note that, workarounds are not necessarily mutually exclusive since security is best done "in depth".

Upgrading Tomcat

For older applications, running on Tomcat with an unsupported Spring Framework version, upgrading to Apache Tomcat 10.0.20,9.0.62, or8.5.78, provides adequate protection. However, this should be seen as a tactical solution, and the main goal should be to upgrade to a currently supported Spring Framework version as soon as possible. If you take this approach, you should consider setting Disallowed Fields as well for defense in depth approach.

Downgrading to Java 8

Downgrading to Java 8 is a viable workaround, if you can neither upgrade the Spring Framework nor upgrade Apache Tomcat.

Disallowed Fields

Another viable workaround is to disable binding to particular fields by setting disallowedFieldson WebDataBinder globally:

@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):

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.

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

7.5 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P