Anatomy of the Apache Struts Vulnerability

How to Exploit the Apache Struts Vulnerability

With good reason, a lot of attention has been given to the recent vulnerability in the Struts MVC framework (CVE-2017-5638). Because of its extensive functionality, Struts is a widely used open source component in web applications. However, these same benefits and Struts’ integration with other frameworks can make upgrades and patches challenging. My goal is to help readers understand how an attacker might exploit this Apache Struts vulnerability. 

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. This is full remote command execution and has been actively exploited in the wild from the initial disclosure. 

DIY Guide to Open Source


The vulnerable code is in the Jakarta Multipart parser. 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 outgoing firewall rules.

HTTP Request With CurlThe 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 and receiving a response.

The OGNL expression sets default access rights to the members of the OgnlContext JAVA object, which represents the execution context of the expression. It empties the blacklist of excluded packages and classes to expose more functionality.

Variable “#eps” is set to the container objects String representation via its toString() method to demonstrate potential manipulation of core servlet parameters safely and to provide a string to return to the user via the system echo command.


#cmds=({'/bin/echo', #eps})

A JAVA ProcessBuilder object is created with the echo command that outputs the String value. Using further JAVA functionality, the input stream of this process is redirected to the output stream of the servlets response. This allows the servlet to respond to the attacker with information, as can be seen with a response:


This command is safe and demonstrates remote command execution, java functionality and an exfiltration channel.

Exploits and proofs of concept for this vulnerability are widely available, substantially lowering the expertise required to execute an attack. Because Struts is widely used, non-targeted attacks are also a likely to occur. 

How Do Mitigate this Vulnerability?

Web application firewalls such as mod_security could mitigate this attack if the rules are set to whitelist valid content types or blacklist OGNL expressions. An alternative mitigation to upgrading Struts is to switch to using Jason Pells multipart parser. This plugin replaces the vulnerable Struts component and can be installed by copying the plugin jar into your application's /WEB-INF/lib directory. The library will need to be included in your application as well.

Sorry we missed you! We close comments for older posts, but we still want to hear from you. Tweet @black_duck_sw to continue the discussion.