Generating
Snort rules to prevent Apache Struts CVE-2017-5638 exploit
Attackers usually exploit vulnerabilities
in software to achieve code execution or gain more privileges on already
compromised system. The most severe vulnerabilities are those that allow remote
code execution without requiring elevated privileges, the situation is even worse
when the exploit is easy to run. This is the case of Apache Struts CVE-2017-5638
which allows remote code execution due to poor validation of input parameters. As defenders, it is important to detect and prevent such vulnerabilities as soon
as possible.
In the ideal world every system should apply the software updates to
fix the vulnerabilities, but in reality it is common that not all systems are
patched due to various reasons. Therefore it is useful to have compensating
controls that will allow detection and/or prevention of the attack. Even if all the best patching practices are followed, these rules can be used to generate intelligence about our adversaries, that can be used to enhance existing defenses or develop new ones. In this
article we will explore how to test this vulnerability in a lab environment in
order to develop a snort rule to detect and prevent attempts to exploit it. As
a second goal we improve the rule to not only log the exploit attempt web
request but also the response sent by the server, which will allow to know if
the exploit attempt was successful or not and assign the proper priority for response and containment.
Lab setup and install
The first step will be to
get the required software mentioned below to setup the vulnerable lab system. I decided to install it on a Windows host, although it can also be installed on a Linux system if you prefer.
- Java Runtime Environment
8u121
- Apache
Tomcat 8.5.13
- Apache Struts vulnerable
version, lower than a 2.3.32 or 2.5.10.1.
Create the environment
variable JRE_HOME and assign it to JRE install Path, in my case it
was “C:\Program Files\Java\jre1.8.0_121”
Start tomcat web server by
running startup.bat script within bin subfolder on tomcat folder.
Check that java.exe is
running on port TCP 8080.
Exploit
test
Download and run
the exploit from http://www.hackplayers.com/2017/03/exploit-rce-para-apache-struts-cve-2017-5638.html. We
can see that the exploit works correctly without any additional modifications;
however it returns the HTML code after the executed command, which is not
desired.
Exploit improvement
By removing
everything after the string “<!DOCTYPE>” we can improve the output.
We run the exploit again and now we only get the result of the command sent.
Snort rule creation
Now that we can
successfully exploit the vulnerability in a lab system, we can develop and test
the snort rule to prevent the attack. By analyzing the exploit, we can see that
the vulnerable header is Content-Type. On normal web requests this header, as its name suggest, is used to indicate the media type of the
resource, valid examples of it are “application”, “audio”, “image”, “multipart”
or similar, as defined on the following RFC document: https://www.w3.org/Protocols/rfc1341/4_Content-Type.html
The exploit
assigns this header to an abnormal value "@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."
With this information we can create a detection rule.
alert tcp any
any -> $HTTP_SERVERS $HTTP_PORTS (sid:900009; rev:1; msg:
"Apache-CVE-2017-563-exploitation-attempt-request";content:"Content-Type";
http_header; content:"@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).";
content:"com.opensymphony.xwork2.ActionContext.container";
flow:established,to_server; priority:80;)
Snort rule
alert tcp any
any -> $HTTP_SERVERS $HTTP_PORTS (sid:900009; rev:1; msg: "Apache-CVE-2017-563-exploitation-attempt-request";content:"Content-Type";
http_header; content:"@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).";
content:"com.opensymphony.xwork2.ActionContext.container";
flow:established,to_server; priority:80;)
Run snort
snort -c
C:\Snort\etc\snortmin.conf -k none -A console -i 1 -q
Snort detection
Run the exploit again and snort should detect it.
If we open the generated pcap with Wireshark we can see the command that the remote attacker attempted to run, in this case the command whoami.
Snort rule
improvement
We have successfully
detected the attack attempt, but the response is not captured only the request,
therefore only based on the generated pcap by Snort, we cannot know if it was
successful. So we will improve the rule to capture the response sent by the
struts web server. To achieve this, we will set a condition using flowbits
option in the first rule and will create
a second rule that will log the response if that variable is set.
Improved rule with flowbits arguments
alert tcp any
any -> $HTTP_SERVERS $HTTP_PORTS (sid:900009; rev:1; msg:
"Apache-CVE-2017-563-exploitation-attempt-request";content:"Content-Type";
http_header; content:"@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).";
content:"com.opensymphony.xwork2.ActionContext.container";flowbits:set,struts_exploit_attempt;
flow:established,to_server; priority:80;)
Rule to log the response
alert tcp $HTTP_SERVERS $HTTP_PORTS -> any any
(msg:"SCILabs-Apache-CVE-2017-563-exploitation-attempt-response";
flowbits:isset,struts_exploit_attempt; flowbits:unset,struts_exploit_attempt;sid:900010; rev:1;
priority:80;)
Snort detection of both request and response
We open the
generated pcap in Wireshark and we can verify that the output generated by the
victim web server has been logged, in this case it is the hostname of the
victim computer.
In case that the
answer is very large, only the first part of the output will be shown, but that
will be enough to determine that the attack has been successful and the nature
of the extracted information. Below you can see the results when the attacker
ran tasklist command.
Finally to
prevent the attack and not just detect it, change “alert” for “drop” on the
first rule in case that an IPS device is available and inline mode is setup.