In March 2017, a critical remote code execution flaw in Apache Struts2 — tracked as CVE-2017-5638 — gave attackers a way to run arbitrary commands on any server running a vulnerable version, with no authentication required. Two months after a patch was published, an unpatched instance of Struts2 running on a consumer dispute portal became the entry point for one of the most consequential data breaches in history: the 2017 Equifax breach, which exposed the personal data of roughly 147.9 million people. This post breaks down the vulnerability itself, how it was weaponized against Equifax, and what security teams should do to make sure they're not sitting on the next version of this same story.
The Vulnerability
CVE-2017-5638 lives in the Jakarta Multipart parser, the component Struts2 uses to handle file uploads and other multipart/form-data requests. The parser's exception-handling logic passed the value of the Content-Type header directly into an OGNL (Object-Graph Navigation Language) expression evaluation without adequate sanitization. OGNL is the expression language Struts2 uses internally to bind HTTP parameters to Java objects — powerful, and dangerous when an attacker gets to control the expression itself.
The exploit path is almost absurdly simple: send a crafted, malformed Content-Type header containing an OGNL payload, and the server evaluates it as code. No login, no CSRF token, no multi-step exploit chain — a single malicious HTTP request is enough to achieve full remote code execution in the context of the web application process. A typical payload looks like:
Content-Type: %{(#_='multipart/form-data')...(#cmd='whoami')...
Because it rides in on a standard content-type header rather than a query parameter or form field, the payload frequently sailed past WAF rulesets and logging pipelines tuned only for parameter-based injection.
Affected Versions and Components
- Apache Struts 2.3.5 through 2.3.31
- Apache Struts 2.5 through 2.5.10
Any application built on these Struts2 versions that accepted file uploads or otherwise routed requests through the Jakarta-based Multipart parser (the default parser implementation) was exploitable out of the box. Given Struts2's popularity as a Java web framework for enterprise portals, insurance systems, e-commerce backends, and — notably — consumer-facing dispute and complaint forms, the exposure was broad and included exactly the kind of internet-facing, PII-handling applications that make for high-value targets.
Severity, Exploitation Likelihood, and KEV Status
- CVSS v3 Base Score: 10.0 (Critical) — unauthenticated, network-exploitable, low complexity, and full compromise of confidentiality, integrity, and availability.
- EPSS: CVE-2017-5638 consistently scores in the highest percentile of the EPSS distribution. Years after disclosure, it remains one of the most actively scanned-for and exploited CVEs on the internet, a status reflected in near-maximal predicted exploitation probability.
- CISA KEV Catalog: Listed in the Known Exploited Vulnerabilities catalog, reflecting confirmed, sustained real-world exploitation — not just theoretical risk.
That combination — maximum severity, maximum exploitation likelihood, and confirmed active use in the wild — is about as close to a "patch this immediately" signal as the vulnerability ecosystem produces.
Timeline
- March 6–7, 2017: The Apache Struts security team discloses CVE-2017-5638 via advisory S2-045 and simultaneously ships fixed releases (2.3.32 and 2.5.10.1). Proof-of-concept exploit code circulates publicly within hours of disclosure.
- Within 48 hours: Mass internet-wide scanning and automated exploitation attempts begin, documented by multiple security research teams tracking opportunistic attackers probing for unpatched Struts2 endpoints.
- March 7–10, 2017: Apache issues public advisories urging immediate upgrades; security vendors publish detection signatures.
- May 13, 2017: Attackers exploit an unpatched Struts2 instance running Equifax's Automated Consumer Interview System (ACIS), a web application used for handling consumer credit disputes. The patch had been available for over two months; Equifax's internal vulnerability scans failed to flag the exposed system as unpatched.
- May–July 2017: Attackers maintain access, moving laterally and exfiltrating data over an extended dwell time before detection — later congressional testimony indicated attacker activity continued for roughly 76 days.
- July 29, 2017: Equifax's security team discovers suspicious network traffic and identifies the intrusion.
- July 30, 2017: The vulnerable web application is taken offline.
- September 7, 2017: Equifax publicly discloses the breach. The initial estimate of 143 million affected US consumers is later revised upward to approximately 147.9 million, with exposed data including names, Social Security numbers, birth dates, addresses, driver's license numbers, and in some cases credit card numbers.
- 2018–2019: Congressional hearings, an SEC investigation into insider trading around the disclosure delay, and a landmark FTC settlement requiring Equifax to pay up to $700 million.
What makes the Equifax case instructive isn't the vulnerability's technical sophistication — it's the gap between "patch available" and "patch applied," and the failure of internal scanning to catch a known-vulnerable, internet-facing component running in production for months.
Remediation Steps
- Upgrade immediately. Move to Struts 2.3.32, 2.5.10.1, or later. Given Struts2's subsequent CVE history (including further OGNL-related RCEs), organizations should standardize on the latest maintained release line rather than treating this single patch as a finish line.
- Inventory every instance. Struts2 is frequently embedded several layers deep in vendor applications, internal tools, and legacy portals that security teams don't actively track. An accurate, automatically maintained software inventory — not a point-in-time scan — is the control that actually would have caught Equifax's exposure.
- If you can't patch immediately, mitigate. Switch the multipart parser to the alternative Jakarta-free implementation (Pell's parser, via the
struts.multipart.parserproperty) as an interim measure, and deploy WAF rules specifically tuned to detect OGNL injection patterns in theContent-Typeheader, not just standard parameters. - Assume breach and limit blast radius. Segment internet-facing applications from sensitive data stores, enforce least-privilege service accounts, and apply egress filtering so that even a successful RCE can't easily exfiltrate data or reach adjacent systems.
- Monitor continuously, not once. Because this CVE remains under active, automated mass-scanning years later, treat any Struts2 exposure as a live detection priority, not a one-time remediation checkbox — verify the fix held after every deployment, config change, and vendor update.
- Close the scan-to-fix gap. Equifax's own scanning tool reportedly failed to detect the vulnerable directory. Validate that your scanning coverage actually reaches every deployed path, and pair detection with a tracked, time-bound remediation SLA for critical, KEV-listed findings.
How Safeguard Helps
CVE-2017-5638 is a textbook case of a known, patched vulnerability going unremediated in a forgotten corner of the application estate — exactly the failure mode Safeguard is built to close. Safeguard's SBOM generation and ingestion capabilities give teams a continuously updated, accurate inventory of every Struts2 (and any other) component across their applications, so vulnerable versions can't hide in unscanned or unowned systems the way Equifax's dispute portal did. Griffin AI, Safeguard's security reasoning engine, correlates that component inventory against live exploitation and KEV data to flag critical-and-actively-exploited findings like this one for immediate attention rather than burying them in a generic severity list. Reachability analysis goes a step further, confirming whether the vulnerable Jakarta Multipart code path is actually invoked in your application's runtime rather than flagging every Struts2 instance equally, so teams triage based on real exploitability. And when a fix is available, Safeguard's auto-fix PRs can open the version bump directly against the affected repository, compressing the "patch available" to "patch deployed" window that, in Equifax's case, stretched to two fatal months.