DEV Community

Vickie Li for ShiftLeft

Posted on • Originally published at blog.shiftleft.io on

Spring4Shell: Spring Remote Code Execution Vulnerability

Spring unauthenticated RCE via classLoader manipulation


Photo by Emile Perron on Unsplash

A critical zero-day vulnerability in the Spring framework was recently reported to Spring’s maintainer, VMWare. The vulnerability is an unauthenticated remote code execution vulnerability that affects Spring MVC and Spring WebFlux applications. You can find the CVE here: https://tanzu.vmware.com/security/cve-2022-22965.

What is affected?

The Spring4Shell RCE vulnerability allows attackers to execute code on applications using the Spring framework before 5.3.18or 5.2.20, with JDK 9+. In addition, applications need to be mapping request parameters into Plain Old Java Objects (POJO) to be vulnerable. Finally, currently available POCs only work on WAR deployments on the Apache Tomcat server.

Because of these mitigating factors, the Spring4Shell vulnerability is not expected to have the wide-ranging impact of the Log4Shell vulnerability we encountered back in December. However, things can change, and more ways to exploit the vulnerability might be found in the future. And although this vulnerability might not affect the majority of Spring applications, its impact is devastating for vulnerable applications.

How does the attack work?

Web applications often need a way to take in user data from requests, and map them into formats that the application can operate on. Spring’s RequestMapping functionality gives developers an easy way to map request parameters. There are different ways of mapping request parameters into Java data types, and one of them is to map request parameters into Java objects.

@Controller 
public class ExampleController {

    @RequestMapping("/signin")
    public String accountHandler(Account account) {
        return "You have signed in!";
    }

}
Enter fullscreen mode Exit fullscreen mode

This code specifies that we have a controller named ExampleController. It will handle requests to the endpoint /signin and the endpoint should take in a parameter called account as the request parameter. The account request parameter will be mapped to an Account object. Now if we send a request to the web service:

http://example.com/signin?name=test
Enter fullscreen mode Exit fullscreen mode

The service will map the request parameter into an Account object with the name field set to test. This is a convenient functionality, but it also introduces security issues. Because if an attacker sends a request parameter containing another Java object, Spring would attempt to map to the appropriate object type. When a request parameter is bound to a Java object like this, the attacker can use the request handler to access the class object. And from there, the attacker can access other valuable object types via the properties of class.

An attacker can achieve RCE by accessing objects of the right classes that can lead to the execution of arbitrary commands. From there, the exploit potential is endless. For example, the attacker can write a web shell onto the server and achieve RCE on the machine. I originally thought that the vulnerability was insecure deserialization, but it is instead a class injection issue similar to this Apache Struts vulnerability: https://nvd.nist.gov/vuln/detail/cve-2014-0094.

How do I remediate this issue?

Spring now has new versions that are not susceptible to the issue. You can find the releases here: https://spring.io/blog/category/releases. If you can upgrade, your application will be safe from the vulnerability. Users of the Spring framework 5.3.x should upgrade to 5.3.18+, and users of 5.2.x should upgrade to 5.2.20+. If you use Spring Boot, versions 2.5.12 and 2.6.6 depend on the safe Spring versions.

If you are not able to upgrade Spring, you can make use of one of these workarounds, both of which will close the attack vector:

  • Tomcat has released new versions that shut down the attack vector, so you can also upgrade to Tomcat versions 10.0.20, 9.0.62, or 8.5.78.
  • Since the exploit requires JDK 9+, downgrading to Java 8 is also an option.

However, since additional ways of exploiting this vulnerability may be found, upgrading Spring is the best course of action. Keep an eye on your application logs and review them for any unusual activity.

Please see Spring’s official announcement (https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement) for a more detailed discussion of the mitigation options and their tradeoffs.

Zero-days found in common dependencies like this one highlights the need to keep your dependencies updated and your software supply chain safe. You can use ShiftLeft CORE (https://www.shiftleft.io/) to help you identify the parts of your code where you’re using vulnerable versions of dependencies, and see whether the affected library is reachable from an untrusted source using Intelligent SCA.


Top comments (0)