Safeguard
Vulnerability Analysis

Spring4Shell RCE vulnerability explained CVE-2022-22965

CVE-2022-22965 (Spring4Shell) lets attackers achieve unauthenticated RCE on Spring MVC/Tomcat apps. Here's the CVSS/EPSS/KEV data, timeline, and fixes.

James
Principal Security Architect
7 min read

On March 30, 2022, the Spring team confirmed a critical remote code execution vulnerability in the Spring Framework, tracked as CVE-2022-22965 and quickly nicknamed "Spring4Shell" by the security community — a nod to the Log4Shell frenzy that had rattled enterprises just months earlier. The vulnerability allows an unauthenticated attacker to achieve full remote code execution on affected servers with a single crafted HTTP request, no credentials or prior access required. Within 48 hours of disclosure, proof-of-concept exploits were circulating publicly and mass scanning activity had already begun. For a framework that underpins a huge share of the world's Java web applications, that combination of severity and reachability made Spring4Shell one of the most consequential vulnerabilities of 2022.

What Makes Spring4Shell Dangerous

Spring4Shell is a data-binding vulnerability rooted in Java's reflection and class-loading model. Spring MVC and Spring WebFlux automatically bind HTTP request parameters to Java object properties — a convenience feature that, without proper restrictions, lets an attacker submit specially crafted parameter names that traverse the object graph of a request via nested getters like class.module.classLoader. On applications running under Apache Tomcat, this chain can be abused to reach the servlet container's internal logging configuration (the AccessLogValve) and rewrite its output path and pattern. By pointing the access log at the webapp's root directory and injecting JSP content into the log pattern, an attacker can cause Tomcat to write a fully functional JSP webshell to disk — and then invoke it directly over HTTP to execute arbitrary commands.

This is conceptually a reincarnation of an older Spring bug (CVE-2010-1622) that was patched over a decade ago by blocking class.* property access. The bypass depends on Java 9's introduction of the Module class, which reintroduced an alternate path to the classloader that the original 2010 fix never accounted for.

Affected Versions and Components

Not every Spring application is exploitable, and the exact conditions matter a great deal when triaging exposure:

  • Spring Framework: versions 5.3.0 through 5.3.17, 5.2.0 through 5.2.19, and older, unsupported branches.
  • Spring Boot: applications built on Spring Framework 5.3.0–5.3.17 or 5.2.0–5.2.19, most commonly surfaced via Spring Boot 2.5.x (pre-2.5.12) and 2.6.x (pre-2.6.6).
  • JDK: Java Development Kit 9 or later (the classloader-based exploitation path does not exist on JDK 8).
  • Servlet container: Apache Tomcat as the deployment target — this was the primary and most reliably exploitable vector.
  • Packaging and dependencies: applications packaged and deployed as a WAR file, using spring-webmvc or spring-webflux, with spring-beans on the classpath.

Applications running as executable Spring Boot JARs with embedded Tomcat were generally assessed as lower risk under the specific Tomcat exploitation chain, but Spring's advisory was explicit that other, undiscovered exploitation vectors involving different application servers or class-loading mechanisms could not be ruled out. Treat "we run embedded Tomcat" as a mitigating factor, not a clean bill of health — the underlying data-binding weakness exists regardless of deployment style.

It's also worth noting that Spring4Shell was disclosed in the same 72-hour window as an unrelated but similarly severe bug, CVE-2022-22963 in Spring Cloud Function, which led to considerable public confusion about which advisory applied to which codebase. Security teams triaging both in real time had to be careful not to conflate patches or scope.

CVSS, EPSS, and KEV Status

  • CVSS: NVD scored CVE-2022-22965 at 9.8 (Critical) — network-exploitable, no privileges or user interaction required, and full impact to confidentiality, integrity, and availability given the RCE outcome.
  • EPSS: The Exploit Prediction Scoring System has consistently placed this CVE in the highest percentile of the entire vulnerability corpus, reflecting sustained, observed exploitation in the wild rather than theoretical risk.
  • CISA KEV: The vulnerability was added to CISA's Known Exploited Vulnerabilities catalog within weeks of disclosure, with a mandated remediation deadline for U.S. federal civilian agencies — a strong independent signal that this was not a "patch when convenient" issue.

Real-world exploitation followed almost immediately: security researchers and vendors observed opportunistic scanning, cryptomining payloads, and webshell drops within days, and the technique was subsequently folded into commodity botnet toolkits, extending the exploitation tail for months after the initial patch was available.

Timeline

  • March 29, 2022: A proof-of-concept exploit for an unpatched, unnamed Spring vulnerability leaks via a GitHub Gist and is screenshotted and shared on Weibo and Twitter before any coordinated advisory is published. The Gist is deleted, but screenshots and mirrors spread rapidly, effectively forcing an early, uncoordinated disclosure.
  • March 30, 2022: Independent researchers and vendors (including Praetorian) reproduce and confirm the exploit against real Spring MVC/Tomcat deployments. VMware/Spring publishes an official advisory and ships fixed releases — Spring Framework 5.3.18 and 5.2.20 — the same day.
  • March 31, 2022: CVE-2022-22965 is formally published in the NVD, and Spring Boot 2.6.6 and 2.5.12, which bundle the patched framework, follow shortly after.
  • Early April 2022: Mass internet-wide scanning and active exploitation attempts are reported by multiple security vendors; VMware issues advisories for downstream products (including Tanzu components) built on vulnerable Spring versions.
  • April 2022: CISA adds CVE-2022-22965 to the Known Exploited Vulnerabilities catalog, confirming active in-the-wild exploitation and setting remediation deadlines for federal agencies.
  • Ongoing (2022–present): The technique persists in commodity malware and botnet campaigns, and continues to surface in scans of legacy, unpatched Spring deployments — a reminder that "patched at disclosure" and "patched everywhere it's actually running" are two very different states.

Remediation Steps

  1. Upgrade the framework first. Update to Spring Framework 5.3.18+ or 5.2.19+... more precisely 5.2.20+, and Spring Boot to 2.6.6+ or 2.5.12+. This is the authoritative fix and should be the end goal for every affected application, not a stopgap.
  2. Patch or upgrade Tomcat as a compensating layer. Apache Tomcat released 10.0.20, 9.0.62, and 8.5.78, which independently block the classloader-manipulation technique even before the application-level fix is applied. If you cannot redeploy immediately, patching Tomcat buys meaningful protection.
  3. Restrict dangerous property binding as a stopgap. If you cannot upgrade Spring immediately, add a global @ControllerAdvice with an @InitBinder method that calls dataBinder.setDisallowedFields("class.*", "Class.*", "*.class.*", "*.Class.*") across all controllers. This closes the specific binding path the exploit relies on without requiring a full dependency bump.
  4. Deploy WAF/virtual patching rules. Block or flag requests containing suspicious parameter names such as class.module.classLoader, class.classLoader, or similar nested reflection paths at the edge, buying time while patches roll out through change management.
  5. Downgrade or pin JDK where feasible. Running affected applications on JDK 8 removes the specific Module-based exploitation path, though this is a mitigation, not a fix, and shouldn't replace patching.
  6. Hunt for indicators of compromise. Search webroot directories for unexpected .jsp files (webshells are frequently dropped with innocuous names), review Tomcat access log configuration for unauthorized changes to output path or pattern, and audit for unfamiliar outbound connections or process spawns from the Tomcat worker process.
  7. Inventory transitive exposure. Spring Framework is frequently pulled in as a transitive dependency of other libraries and internal platform frameworks — confirm you've identified every affected artifact, not just your directly declared dependencies, before declaring remediation complete.

How Safeguard Helps

Spring4Shell is a textbook case for why version matching alone isn't enough — the vulnerability is only exploitable under a specific combination of JDK version, servlet container, deployment packaging, and reachable code path, and flagging every application that merely depends on an affected Spring version buries real risk in noise. Safeguard's reachability analysis traces whether the vulnerable data-binding path in your specific application is actually invocable from an untrusted entry point, so your team can triage Spring4Shell-class findings by exploitability rather than chasing every dependency match. Griffin, Safeguard's AI security analyst, correlates that reachability signal with your deployment context — Tomcat versus embedded server, WAR versus JAR, JDK version — to explain in plain language which services are truly exposed and why. Continuous SBOM generation and ingestion give you a live inventory of every direct and transitive Spring dependency across your fleet, closing the "we didn't know it was in there" gap that let Spring4Shell linger in production long after patches shipped. When remediation is confirmed necessary, Safeguard can open auto-fix pull requests that bump the framework and Spring Boot versions to the patched releases, cutting the time between advisory and deployed fix from weeks to hours.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.