SpringShell RCE vulnerability: Guidance for protecting against and detecting CVE-2022-22965

On March 31, 2022, vulnerabilities in the Spring Framework for Java were publicly disclosed. Microsoft is currently assessing the impact associated with these vulnerabilities. This blog is for customers looking for protection against exploitation and ways to detect vulnerable installations on their network of the critical remote code execution (RCE) vulnerability CVE-2022-22965 (also known as SpringShell or Spring4Shell).

The Spring Framework is the most widely used lightweight open-source framework for Java. In Java Development Kit (JDK) version 9.0 or later, a remote attacker can obtain an AccessLogValve object through the framework’s parameter binding feature and use malicious field values to trigger the pipeline mechanism and write to a file in an arbitrary path, if certain conditions are met. 

The vulnerability in Spring Core—referred to in the security community as SpringShell or Spring4Shell—can be exploited when an attacker sends a specially crafted query to a web server running the Spring Core framework. Other vulnerabilities disclosed in the same component are less critical and not tracked as part of this blog.

Impacted systems have the following traits:

  • Running JDK 9.0 or later
  • Spring Framework versions 5.3.0 to 5.3.17, 5.2.0 to 5.2.19, and earlier versions
  • Apache Tomcat as the Servlet container
  • Packaged as a traditional Java web archive (WAR) and deployed in a standalone Tomcat instance; typical Spring Boot deployments using an embedded Servlet container or reactive web server are not impacted
  • Tomcat has spring-webmvc or spring-webflux dependencies

Any system using JDK 9.0 or later and using the Spring Framework or derivative frameworks should be considered vulnerable. The following nonmalicious command can be used to determine vulnerable systems:

$ curl host:port/path?class.module.classLoader.URLs%5B0%5D=0

A host that returns an HTTP 400 response should be considered vulnerable to the attack detailed in the proof of concept (POC) below. Note that while this test is a good indicator of a system’s susceptibility to an attack, any system within the scope of impacted systems listed above should still be considered vulnerable.

The threat and vulnerability management console within Microsoft 365 Defender provides detection and reporting for this vulnerability.

Observed activity

Microsoft regularly monitors attacks against our cloud infrastructure and services to defend them better. Since the Spring Core vulnerability was announced, we have been tracking a low volume of exploit attempts across our cloud services for Spring Cloud and Spring Core vulnerabilities. For CVE-2022-22965, the attempts closely align with the basic web shell POC described in this post.

Attack breakdown

CVE-2022-22965 affects functions that use request mapping annotation and Plain Old Java Object (POJO) parameters within the Spring Framework. The POC code creates a controller that, when loaded into Tomcat, handles HTTP requests.

The only publicly available working POC is specific to Tomcat server’s logging properties via the ClassLoader module in the propertyDescriptor cache. The attacker can update the AccessLogValve class using the module to create a web shell in the Tomcat root directory called shell.jsp. The attacker can then change the default access logs to a file of their choosing.

Screenshot of an application UI with lines of code. One of said code lines is highlighted, with an annotation written in a non-English language.
Figure 1. Screenshot from the original POC code post

The changes to AccessValveLog can be achieved by an attacker who can use HTTP requests to create a .jsp file in the service’s root directory. In the example below, each GET parameter is set as a Java object property. Each GET request then executes a Java code resembling the example below, wherein the final segment “setPattern” would be unique for each call (such as setPattern, setSuffix, setDirectory, and others): 

Screenshot of Java codes of an actual exploit.
Screenshot of several lines of HTTP URLs.
Figure 2. Screenshot from the original POC code post
Screenshot of an application UI with lines of code.
Figure 3. Screenshot from the original POC code post

The .jsp file now contains a payload with a password-protected web shell with the following format:

Screenshot of the payload's web shell code.

The attacker can then use HTTP requests to execute commands. While the above POC depicts a command shell as the inserted code, this attack could be performed using any executable code.

The vulnerability and exploit in depth

The vulnerability in Spring results in a client’s ability, in some cases, to modify sensitive internal variables inside the web server or application by carefully crafting the HTTP request.

In the case of the Tomcat web server, the vulnerability allowed for that manipulation of the Access Log to be placed in an arbitrary path with somewhat arbitrary contents. The POC above sets the contents to be a JSP web shell and the path inside the Tomcat’s web application ROOT directory, which essentially drops a reverse shell inside Tomcat. For the web application to be vulnerable, it needs to use Spring’s request mapping feature, with the handler function receiving a Java object as a parameter.

Background

Request mapping and request parameter binding

Spring allows developers to map HTTP requests to Java handler methods. The web application’s developer can ask Spring to call an appropriate handler method each time a user requests a specific URI. For instance, the following web application code will cause Spring to invoke the method handleWeatherRequest each time a user requests the URI /WeatherReport:

@RequestMapping(“/WeatherReport”)
public string handleWeatherRequest(Location reportLocation)
{
…
}

Moreover, through request parameter binding, the handler method can accept arguments passed through parameters in GET/POST/REST requests. In the above example, Spring will instantiate a Location object, initialize its fields according to the HTTP request’s parameters, and pass it on to handleWeatherRequest. So, if, for instance, Location will be defined as:

class Location
{
    public void setCountry(string country) {…}
    public void setCity(string city) {…}
    public string getCountry() {…}
    public string getCity() {…}
}

If we issue the following HTTP request:

example.com/WeatherReport?country=USA&city=Redmond

The resulting call to handleWeatherRequest will automatically have a reportLocation argument with the country set to USA and city set to Redmond.

If Location had a sub-object named coordinates, which contained longitude and latitude parameters, then Spring would try and initialize them out of the parameters of an incoming request. For example, when receiving a request with GET params coordinates.longitude=123&coordinate.latitude=456 Spring would try and set those values in the coordinates member of location, before handing over control to handleWeatherRequest.

The SpringShell vulnerability directly relates to the process Spring uses to populate these fields.

The process of property binding

Whenever Spring receives an HTTP request mapped to a handler method as described above, it will try and bind the request’s parameters for each argument in the handler method. Now, to stick with the previous example, a client asked for:

example.com/WeatherReport?x.y.z=foo

Spring would instantiate the argument (in our case, create a Location object). Then it breaks up the parameter name by dots (.) and tries to do a series of steps:

  1. Use Java introspection to map all accessors and mutators in location
  2. If location has a getX() accessor, call it to get the x member of location
  3. Use Java introspection to map all accessors and mutators in the x object
  4. If the x object has a getY() accessor, call it to get the y object inside of the x object
  5. Use Java introspection to map all accessors and mutators in the y object
  6. If the y object has a setZ() mutator, call it with parameter “foo”

So essentially, ignoring the details, we get location.getX().getY().setZ(“foo”).

The vulnerability and its exploitation

Prelude: CVE-2010-1622

In June 2010, a CVE was published for the Spring framework. The crux of the CVE was as follows:

  1. All Java objects implicitly contain a getClass() accessor that returns the Class describing the object’s class.
  2. Class objects have a getClassLoader() accessor the gets the ClassLoader object.
  3. Tomcat uses its own class loader for its web applications. This class loader contains various members that can affect Tomcat’s behavior. One such member is URLs, which is an array of URLs the class loader uses to retrieve resources.
  4. Overwriting one of the URLs with a URL to a remote JAR file would cause Tomcat to subsequently load the JAR from an attacker-controlled location.

The bug was fixed in Spring by preventing the mapping of the getClassLoader() or getProtectionDomain() accessors of Class objects during the property-binding phase. Hence class.classLoader would not resolve, thwarting the attack.

The current exploit: CVE-2022-22965

The current exploit leverages the same mechanism as in CVE-2010-1622, bypassing the previous bug fix. Java 9 added a new technology called Java Modules. An accessor was added to the Class object, called getModule(). The Module object contains a getClassLoader() accessor. Since the CVE-2010-1622 fix only prevented mapping the getClassLoader() accessor of Class objects, Spring mapped the getClassLoader() accessor of the Module object. Once again, one could reference the class loader from Spring via the class.module.classLoader parameter name prefix.

From ClassLoader to AccessLogValve

The latest exploit uses the same accessor chaining, via the Tomcat class loader, to drop a JSP web shell on the server.

This is done by manipulating the properties of the AccessLogValve object in Tomcat’s pipeline. The AccessLogValve is referenced using the class.module.classLoader.resources.context.parent.pipeline.first parameter prefix.

The following properties are changed:

  1. Directory: The path where to store the access log, relative to Tomcat’s root directory. This can be manipulated to point into a location accessible by http requests, such as the web application’s directory.
  2. Prefix: The prefix of the access log file name
  3. Suffix: The suffix of the access log file name. The log file name is a concatenation of the prefix with the suffix.
  4. Pattern: A string that describes the log record structure. This can be manipulated so that each record will essentially contain a JSP web shell.
  5. FileDateFormat: Setting this causes the new access log settings to take effect.

Once the web shell is dropped on the server, the attacker can execute commands on the server as Tomcat.

Discovery and mitigations

How to find vulnerable devices

Threat and vulnerability management capabilities in Microsoft Defender for Endpoint monitor an organization’s overall security posture and equip customers with real-time insights into organizational risk through continuous vulnerability discovery, intelligent prioritization, and the ability to seamlessly remediate vulnerabilities.

Customers can now search for CVE-2022-22965 to find vulnerable devices through the Weaknesses page in threat and vulnerability management.

Screenshot of the Weaknesses page where one can search for CVE-2022-22965 to find vulnerable devices.
Figure 4. Weaknesses page in Microsoft Defender for Endpoint

Enhanced protection with Azure Firewall Premium

Customers using Azure Firewall Premium have enhanced protection from the SpringShell CVE-2022-22965 vulnerability and exploits. Azure Firewall Premium Intrusion Detection and Prevention System (IDPS) provides IDPS inspection for all east-west traffic, outbound traffic to the internet, and inbound HTTP traffic from the internet. The vulnerability rulesets are continuously updated and include vulnerability protection for SpringShell since March 31, 2022. The screenshot below shows all the scenarios which are actively mitigated by Azure Firewall Premium.

Configure Azure Firewall Premium with both IDPS Alert & Deny mode and TLS inspection enabled for proactive protection against CVE-2022-22965 exploit.  

Screenshot of the Azure Firewall Premium portal UI displaying alerts related to CVE-2022-22965 exploit attempts.
Figure 5. Azure Firewall Premium portal detecting CVE-2022-22965 exploitation attempts.

Customers using Azure Firewall Standard can migrate to Premium by following these directions. Customers new to Azure Firewall Premium can learn more about Firewall Premium.

Patch information and workarounds

Customers are encouraged to apply these mitigations to reduce the impact of this threat. Check the recommendations card in Microsoft 365 Defender threat and vulnerability management for the deployment status of monitored mitigations.

  • An update is available for CVE-2022-22965. Administrators should upgrade to versions 5.3.18 or later or 5.2.19 or later. If the patch is applied, no other mitigation is necessary.

If you’re unable to patch CVE-2022-22965, you can implement this set of workarounds published by Spring:

  • Search the @InitBinder annotation globally in the application to see if the dataBinder.setDisallowedFields method is called in the method body. If the introduction of this code snippet is found, add {"class.*","Class.*","*.class.*", "*.Class.*"} to the original blacklist. (Note: If this code snippet is used a lot, it needs to be appended in each location.)
  • Add the following global class into the package where the Controller is located. Then recompile and test the project for functionality:
import org.springframework.core.annotation.Order; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.InitBinder; @ControllerAdvice @Order(10000) public class GlobalControllerAdvice{ @InitBinder public void setAllowedFields(webdataBinder dataBinder){ String[]abd=new string[]{"class.*","Class.*","*.class.*","*.Class.*"}; dataBinder.setDisallowedFields(abd); } }

Detections

Microsoft 365 Defender

Endpoint detection and response (EDR)

Alerts with the following title in the security center can indicate threat activity on your network:

  • Possible SpringShell exploitation

The following alerts for an observed attack, but might not be unique to exploitation for this vulnerability:

  • Suspicious process executed by a network service

Antivirus

Microsoft Defender antivirus version 1.361.1234.0 or later detects components and behaviors related to this threat with the following detections:

  • Trojan:Python/SpringShellExpl
  • Exploit:Python/SpringShell
  • Backdoor:PHP/Remoteshell.V

Hunting

Microsoft 365 Defender advanced hunting queries 

Use the query below to surface exploitation of CVE-2022-22965 on both victim devices and devices performing the exploitation. Note that this query only covers HTTP use of the exploitation and not HTTPS.

DeviceNetworkEvents
| where Timestamp > ago(7d)
| where ActionType =~ "NetworkSignatureInspected"
| where AdditionalFields contains ".jsp?cmd="
| summarize makeset(AdditionalFields, 5), min(Timestamp), max(Timestamp) by DeviceId, DeviceName 

READ MORE HERE