CVE-2017-5638: Apache Struts 2 Content-Type RCE, check and fix
Last updated:
In Apache Struts 2, the Jakarta multipart parser builds its error message from the Content-Type header of a failed upload, and evaluates it as OGNL. An attacker sends a request with an OGNL expression in that header and runs commands on the server, without logging in.
It was exploited in the wild from March 2017 and used in large data breaches. Old Struts applications still run in many companies, so the scans continue.
At a glance
- CVE
- CVE-2017-5638
- Software
- Apache Struts 2
- Affected versions
- 2.3.5 to 2.3.31, 2.5 to 2.5.10
- Fixed in
- 2.3.32, 2.5.10.1
- CVSS score
- 9.8 Critical (NVD, CVSS 3.1) ·
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - CISA Known Exploited Vulnerabilities
- Yes, added on November 3, 2021
- Published by NVD
- March 11, 2017
- InfraFence virtual patch
vp-cve-2017-5638(ModSecurity id 9920007)
What is affected
According to Apache's bulletin S2-045: Struts 2.3.5 to 2.3.31 and 2.5 to 2.5.10, with the default Jakarta multipart parser. Struts is a library inside Java web applications (struts2-core-*.jar), not a system package.
Check whether a server has it
Look for the library and for applications that bundle it; the version is in the name:
sudo nice -n 19 ionice -c3 find / -xdev -type f -name 'struts2-core-*.jar' 2>/dev/nullsudo nice -n 19 ionice -c3 find / -xdev -type f \( -name '*.war' -o -name '*.ear' \) 2>/dev/null \
| while read -r f; do
unzip -l "$f" 2>/dev/null | grep -oE 'struts2-core-[0-9][^/ ]*\.jar' | sed "s|^|$f: |"
doneFix it
- Upgrade Struts to 2.3.32 or 2.5.10.1 at least, the releases that fixed it. Both lines are long out of support: plan the move to a supported Struts release, which also closes the later vulnerabilities.
- Rebuild and redeploy the application, then restart it.
- If you cannot upgrade at once, Apache's bulletin gives two workarounds: a servlet filter that rejects requests whose
Content-Typeis not a plainmultipart/form-data, or switching to another multipart parser.
Warning: An application that ran a vulnerable Struts on the internet may have been compromised years ago: look for unknown accounts, scheduled tasks and web shells.
How InfraFence blocks it while you update
The virtual patch for CVE-2017-5638 is a ModSecurity rule on the Content-Type request header: it blocks a header that contains %{ or ${, the start of an OGNL expression. A genuine Content-Type never contains either.
Note: The same bug can also be reached through the Content-Disposition and Content-Length headers of an upload (CVE-2017-5638 covers them; Apache's S2-046 describes them). The patch checks only Content-Type, the form exploited in the wild. The upgrade covers all of them.
How the patch is applied
- The agent notes which SSH ports and sites answer.
- It writes the rule (ModSecurity id 9920007) between its own markers in its ModSecurity file, runs
apachectl configtestand reloads Apache gracefully. A failed test puts the previous file back. - It checks that SSH and the sites still answer, and removes the patch if they do not.
- It checks that ModSecurity really blocks with the rule, with a harmless local probe request. A ModSecurity in
DetectionOnlyonly logs: the patch is then removed and reported as ineffective, never as applied.
Every request the patch blocks is reported with CVE-2017-5638 (agent 1.0.37 or later): you see the attempts on the server's activity and on the Exploitation page of the dashboard, so you know the vulnerability is being tried against you.
Warning: A virtual patch blocks the known form of the attack on the requests that go through Apache on that server. It is not a substitute for the update: install the fixed version, then remove the patch from Activity with Undo if you no longer need it.
Virtual patches need Apache with ModSecurity, the setting Allow web server configuration changes, and no hosting panel or configuration manager in charge of the web server; they are part of the Pro plan and AutoMode. A person applies them from the AI analysis, or AutoMode does. See Virtual patches.
Sources
The facts on this page come from these sources; check them for changes.
Try it free on 1 server
Starter is free for one server, with full protection and automatic blocking. No credit card.
Install the agent as root, with your token in place of <TOKEN>:
curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --token <TOKEN>The token is created in the dashboard, in Servers › Add server.
