Spring Core RCE or Spring4Shell

A vulnerability has been disclosed on Spring Framework which leads to remote code execution. A CVE is assigned to it recently with the code CVE-2022–22965. In this small post, we will try to give some details of the vulnerability and exploitation, however, we will also try to shed some light on the root cause of the weakness and analyze the mitigation Spring team published on the new versions.

Spring4Shell is the newest popular remote code execution vulnerability disclosed

Is My Application Vulnerable?

There is some confusion with the configuration that your application has to have in order to be classified as vulnerable. However, this is more or less the target spec;

  • using JDK 9 and above
  • and using Spring Frameworks up to 5.3.17 or 5.2.19

The application also should be a Spring MVC project accepting HTTP requests and deployed specifically as a WAR file to a Apache Tomcat Servlet container.

What is The Best Mitigation?

The best mitigation is to upgrade your Spring versions to 5.3.18 or 5.2.20. Spring Boot versions that depend on Spring Framework 5.3.18 have also being released.

Moreover, while the root cause of the weakness is not on Apache Tomcat, they also released versions (10.0.20, 9.0.62, and 8.5.78) that prevent the attack vectors being used. This is an alternative mitigation technique not the best recommendation. However, if you use older versions of the Spring Framework and can’t upgrade, then this might be the quickest and the most secure option.

Alternative Mitigation Techniques

There are also other mitigation techniques, such as using downgrading your JDK to 8, which doesn’t have the feature that the published attack vector is using. More on this at the end of this post.

Another mitigation technique, but this time involving programming, promotes a black list and a white list approaches. As we all know the black list approaches are weaker so, let’s start with that.

Implementing a WebDataBinder

@ControllerAdvice
@Order(1000)
public class BinderControllerAdvice {

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

Placing this at the same package with your Controllers located, the Spring Framework won’t allow attackers to bind the parameters including class or Class words in it.

Why? Because the attackers will send HTTP POST parameters that should include these words in order to exploit the vulnerability as shown below highlighted with yellow.

A simple exploitation of Spring4Shell by using POST parameters that contain class words

And why do you think, the disallowed list contains both upper case and lower case C characters? Because there’s a discrepancy between the actual binding and applying this disallowed list to the parameter names in Spring :) If we only use a lower case c in the code above, the attacker can easily bypass it by using an upper case C and the exploit would still work.

That alone says that while this alternative is a quick mitigation, it is not the best one. So, here’s the alternative that employs a white list;

Override the initBinder for all Controllers

In this mitigation alternative, we have to override initBinder method of all Controllers that uses RequestMapping on their actions through a POST method.

@InitBinder
public void initBinder(WebDataBinder binder){
binder.setAllowedFields(new String[]{ "fullname",
"lastname",
"age",
"dob",
"bio",
"email" });
}

The above is an example code block for a Controller that only these parameter names should be taken as the input from the client application.

Implementing this for every Controller would be a terrific way of using white listing that will not only prevent this bug without upgrading (not that we recommend not upgrading) but also will probably prevent other future weaknesses resulting in insecure handling of dynamic class loading of underlying frameworks, Spring MVC in this case.

However, albeit a good one, this method is a highly unlikely one to be followed since it may require a substantial amount of work and, moreover, it should be maintained and tested well. Since an unfortunate miss in the white list in the next deployment, the application won’t work because a new field or a change in one of the existing fields is not in the allowed fields list anymore.

And last but not the least, web application firewall rules can be applied to prevent this vulnerability to be abused by hackers. The rules will be aligned with the black list applied in the above code piece with the WebDataBinder.

A Word On The Exploitation

It takes some time and trial/errors to build a PoC environment and a successful exploit code, however, all an attacker has to do is to send a specifically crafted but simple POST requests to the target servers, preferably utilizing Spring Framework.

As a side note, most of the PoC exploitation strings published in GitHub or web sites contain one or more syntax errors, however, this can be fixed with small amount of work such as appropriate HTTP headers or using valid URL encoding. But this is not our focus.

Adding valid HTTP headers that will be replaced in the exploitation string

The basic idea is that this is a relatively easy to exploit vulnerability and easy to be automated for ransomware purposes. Therefore, it should be taken seriously.

The Root Cause

Any MVC framework supports an automated binding through HTTP methods from user provided parameters to back-end model objects. This is a live saver for developers.

However, in order to pull this task off, the frameworks should dynamically create instances of classes and bind the parameter names and values sent as the names and values by the end-user. As history has been showing us, this is messy and highly complicated to make it right.

Spring4Shell is not an exception. Let’s see the fixing code and try to get some high level lessons out of it. But before that, let’s first see again the list of part of the HTTP POST parameter names that are being used to exploit the weakness;

class.module.classLoader.resources.context...first.pattern
class.module.classLoader.resources.context...first.suffix
class.module.classLoader.resources.context...first.directory
class.module.classLoader.resources.context...first.prefix
class.module.classLoader.resources.context...first.fileDateFormat

The below code is the part of the bug-fix for Spring Framework. The red part was taken out of the vulnerable code and the green part is inserted as a fix. From a high level, looking at the red part, the word classLoader was being prohibited as well as the protectionDomain. Since the methods (properties) that mapping to these words would allow malicious users to mess around at the back-end. Trying to avoid bad things is black-listing. And this is one.

A part of the bug fix code for Spring4Shell vulnerability

The green part on the other hand, follows a more like a whitelist approach. Any method other than name or ending with name is excluded. If you look at one of the JavaDocs explaining the Class, you will see that here the framework developers consider methods with Name, and ending with Name safe to be bound by external users, but not others.

The reason the red part was secure enough for applications using JDK prior to 9 was that, with JDK 9 a new method is added to Class called module which also contained ClassLoaders and the attackers actually use this method (property) to bypass it.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store