On March 29, 2022, a Chinese cybersecurity research firm leaked an attack that could impact most enterprise Java applications, globally. An investigation of the issue showed that the root cause was a security vulnerability in the widely used, free, community-developed, open-source programming framework called Spring Core.
What is Spring Core?
The Spring Framework is the foundation for most enterprise applications written in the Java programming language. Our recent data showed Spring Core as being used by 74% of Java applications. Specifically, Spring provides the "plumbing" of enterprise applications so that teams can focus on application-level business logic, without unnecessary ties to specific deployment environments.
What is Spring4Shell?
As of Wednesday, March 30, the Contrast Security Labs team confirmed the Spring zero-day vulnerability by use of a public Proof of Concept (PoC), Spring4Shell, which could be the source of Remote Code Execution (RCE).
Spring translates the body and parameters of an HTTP request and turns them into a domain object for developers to use. This makes their lives easier.
In the process of building an object graph to give to the developer, Spring takes special care not to let attackers control any parts of the Class, ProtectionDomain, and ClassLoader of the instance being created. Unfortunately, changes to the Class object in Java 9 meant the checks Spring performed were no longer enough.
The Spring code in question is shown here:
https://github.com/spring-projects/spring-framework/blob/b595dc1dfad9db534ca7b9e8f46bb9926b88ab5a/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java#L288
PropertyDescriptor[] pds = this.beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
if (Class.class == beanClass && ("classLoader".equals(pd.getName()) || "protectionDomain".equals(pd.getName()))) {
// Ignore Class.getClassLoader() and getProtectionDomain() methods - nobody needs to bind to those
continue;
}
This code attempts to restrict access from overriding these object graph paths:
- Class.getClassLoader() -> ClassLoader
- Class.getProtectionDomain() -> ProtectionDomain
However, because the Class object now exposes a getModule() method, attackers can now take this slightly different path:
- Class.getModule() -> Module -> Module.getClassLoader()
The introduction of Class#getModule() couldn’t have been directly foreseen when they wrote this code, although we could have a spirited debate about the robustness of this style of check.
The consequences of handing users control of properties of the ClassLoader depend on the features of the ClassLoader being exploited.
The exploit and PoC being run around shows an attacker exploiting features of Tomcat 9’s WebAppClassLoaderBase. The exploit works in a few stages:
- The attacker changes the target of the ClassLoader’s logging facility to create a new, malicious JSP file
- The attacker uses a few tricks to write malicious code into the JSP file, creating a backdoor
- The attacker then makes a request to the new backdoor JSP which then invokes system commands
Java 9 was released in July of 2017, so this Spring zero-day vulnerability has been exploitable in production apps and APIs for five years.
The Spring boot application vulnerability video below shows the exploit in a few quick requests. The exploit posts a payload to the index of the basic Spring boot application. The exploit takes advantage of the missing binding configuration and creates a malicious JSP on the filesystem in a web-accessible directory. From there, a request is sent with the “id” command to request the current ID of the user which returns as “uid=0(root) gid=0(root) groups=0(root)” which shows in this case the application is running as root.
How do I know if I’m vulnerable to Spring4Shell?
There are a few requirements for an application to be vulnerable to the Spring4Shell zero-day vulnerability:
- You use a Spring app (up to and including version 5.3.17)
- Your app runs on Java 9+
- You use form binding with name=value pairs – not using Spring’s more popular message conversion of JSON/XML
- You don’t use an allowlist -OR- you don’t have a denylist that blocks fields like “class”, “module”, “classLoader”
What are the vulnerable conditions for the currently circulating Spring exploit?
All of the above, plus you must be running Tomcat (unknown ranges of versions yet, but certainly including 9), because the exploit takes advantage of Tomcat’s ClassLoader and logging facility to write a malicious, backdoor JSP.
It’s prudent to assume that exploits will be coming that take advantage of different class loaders or another environment context and that any vulnerable Spring applications that satisfy the conditions of the first section will be vulnerable.
How do I mitigate the Spring security vulnerability issue?
For now, Contrast Labs recommends:
1) Upgrade Spring Framework to 5.3.18 or 5.2.20 which mitigates the vulnerability.
2) If you cannot upgrade, for all who are using Spring core and binding to non-basic types such as POJOs, set the allowed fields to specify the only bindings you wish your application to use
- Spring Documentation: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/DataBinder.html#:~:text=fields%20when%20binding.-,setAllowedFields,-public%C2%A0void%C2%A0setAllowedFields
3) For Contrast customers, Protect can detect and block the current public exploit circulating the web. However, exploit writers will find ways around it quickly. The exploit in circulation installs a backdoor that is simple to detect and block. We are working on more robust controls at the moment and will release them as soon as possible.
For now, to protect against the currently circulating exploit, make sure Contrast Protect is enabled on your Spring applications (especially those on JDK 9+). As you can see in the video below, when Protect is configured properly, it blocks the attack.
Spring4Shell with Protect Video:
To help protect your applications from the currently circulating exploit here are the settings you should enable in your Protect monitored applications in blocking mode.
(a) Command Injection in blocking mode
(b) For more visibility of attacks targeting your environment - Enable CVE Shields for CVE-2014-0112 and CVE-2014-0114 (these specific CVE shields are for Struts issues, however, due to the similar nature of the payloads, this provides visibility into attacks through Probes)
What’s next?
We have published communication to our Support Portal letting customers know we are researching implications and we will let them know exactly how they can fix this Spring4Shell zero-day vulnerability in their systems. Our team is currently researching the ability to exploit this vulnerability outside of a Tomcat environment.
As always, Contrast will continue to monitor the situation with the Spring4Shell security vulnerability. The security of our customers is of utmost importance to us. If you have any questions, concerns, or would like to discuss this issue further, please don’t hesitate to reach out to us at support@contrastsecurity.com.
Watch our live webinar recording "CISO Guidance on Spring4Shell" as the Contrast Labs team reviews the latest details of Spring4Shell and how to protect yourself now and moving forward.
*This blog article will include updates about Spring4Shell as they become available.