Examining CVE-2017-9791: New Apache Struts Remote Code Execution Vulnerability
By Govind Sarda (Vulnerability Research)
The Apache Struts framework is useful for building modern Java-based web applications, with two major versions, Apache Struts 1 and Apache Struts 2, released so far. Support for Apache Struts 1 ended in 2008 with the adoption of Apache Struts 2, which reached its first full release at the start of 2007. A Struts 1 plugin is available that allows developer to use existing Struts 1 Actions and ActionForms in Struts 2 web applications. A vulnerability has been found in this plugin that could allow remote code execution on the affected server, if used with Struts 2.3.x. (Versions 2.5.x are not affected.)
Previous incidents have shown that remote code execution (RCE) vulnerabilities in Apache Struts used Object Graph Navigation Language (OGNL) expressions. The use of OGNL makes it easy to execute arbitrary code remotely because Apache Struts uses it for most of its processes. A recently disclosed Struts vulnerability, CVE-2017-9791 (covered in S2-048) also uses OGNL expressions for Remote Code Execution.
For a remote code execution to be successful, the attacker needs to send a specially crafted request with a malicious value in the vulnerable parameter to the vulnerable server, which is using the Struts 2 – Struts 1 plugin and a Struts 1 action with the value part of a message being presented to the user. An example of this is when an untrusted input value is used as a part of the error message in the ActionMessage class.
The attacker can then send malicious code in the HTTP request or body as a parameter value that will be run on the targeted server hosting a vulnerable application. A proof of concept that demonstrates the attack scenario is publicly available.
When one looks at the solution provided by the vendor, it clearly mentions to always use resource keys instead of passing a raw message to the ActionMessage, as shown below:
messages.add(“msg”, new ActionMessage(“struts1.gangsterAdded”, gform.getName()));
A raw value should never be passed, as in the example below:
messages.add(“msg”, new ActionMessage(“Gangster ” + gform.getName() + ” was added”));
The Struts Showcase app is an example of a web application that does the above. This comes with the Struts 2.3.x series, and it also used the Struts 1 plugin—specifically, in the integration of struts2-showcase under the SaveGangsterAction class execute method (located in the SaveGangsterAction.java file).
This method pulls a user-controlled parameter value directly from gform.getName() into the message structure. The value picked by gform.getName() is not sanitized before it is passed on to different methods and since it is user controlled, OGNL expressions can be embedded in it. A call to getText(msg.getKey () …) is also made, which is able to execute the OGNL expression from subsequent calls to different methods in its implementation.
Apache Struts versions 2.3.x with Struts 1 plugin and Struts 1 action are reported to be Vulnerable. If you are using such configuration, to fix this issue, the vendor has suggested always using resource keys instead of passing a raw message to the ActionMessage or use Apache Struts 2.5.x series.
Trend Micro Solutions
Deep Security™ provides protection from any threats that may target this vulnerability via the following DPI rule:
- 1008490 – Apache Struts2 Struts 1 Plugin Showcase Remote Code Execution Vulnerability (CVE-2017-9791)
TippingPoint has posted a Customer Shield Writer (CSW) file for this vulnerability that are available for customers to download on TMC. The applicable rules are as follows:
- C000001: HTTP: Apache Struts 2 Struts1 Plugin Code Execution Vulnerability
- C000002: HTTP: Struts 2 Struts 1 SaveGanster.action Showcase Site Access
- C000003: HTTP: Apache Struts 2 Suspicious opensymphony Actions
- C000004: HTTP: Apache Struts 2 Echo Command Usage