Analyzing CVE-2017-9791: Apache Struts Vulnerability Can Lead to Remote Code Execution

Apache Struts is a model-view-controller framework for creating Java web applications. Struts has suffered from a couple of vulnerabilities using the technique of object-graph navigation language (OGNL) injection. OGNL is an expression language that allows the setting of object properties and execution of various methods of Java classes. OGNL can be used maliciously to perform remote code execution attacks against Apache servers. In this post, we will analyze the recent vulnerability CVE-2017-9791 and offer a debugging example to demonstrate how OGNL attacks work on Apache Struts.

The vulnerability is present in Struts 2.3.x (prior to Version 2.3.33) with the Struts1 plug-in and Struts1 action classes. In some cases, untrusted input is presented to the user. For this analysis, we will use one of the examples in the Showcase integration app that uses these components.

 

Analyzing the patch diff

The following screen shows part of the patch for the file SaveGangsterAction.java, part of integration app, as taken from https://github.com/apache/struts/commit/73da12e723c2737bd515946588ddcd898acf584a:

Taking a closer look at the preceding image, we can see that the argument to the function messages.add has been slightly changed in the patch and “Struts1.gangsterAdded” has been introduced, and is defined in the globalMessages.properties:

Struts1.gangsterAdded is a key with the value “Gangster {0} added successfully.” It will avoid executing the OGNL code, thus fixing the issue, as we will see.

Debugging the code

When we open the Struts2 Showcase integration app, we can see that it expects name, age, and other parameters and then displays the value of the “name” field on the confirmation screen:

The name will be the vulnerable parameter. This is where we can provide OGNL code to confirm the vulnerability. A simple way to confirm the OGNL vulnerability is to provide a test input as ${1+1} or %{1+1}.

Upon entering ${1+1} in the name field and setting a breakpoint on the code, we can see that it calls the function action.execute in Struts1Action.java:

This step calls the vulnerable code, which creates an action message with the parameters we have provided:

Next the code calls the method addMessage in Action.java, which saves the message in “requestMessage” list:

Following this step, control returns to Struts1Action.java. Tracing the code further, we can see that the control flow reaches to the function getText method in TextProviderSupport.Java:

The code calls the method findText in LocalizeTextUtil.Java. This method is responsible for finding the local message for the key; it also evaluates the OGNL code, as we can see from comments in the code. The key is aTextName, as mentioned in the preceding image:

If this method is unable to find a message for the provided key, then it calls the getDefaultMessage method:

As we can see in the preceding image, there is a call to the TextParseUtil.translateVariables method, which calls another overloaded method, translateVariables, as follows:

As we can see in the following screenshot, the translateVariables method calls the parser.evaluate method from OgnlTextParser.java with the key or message we found in the preceding image, as follows:

The Parser.evaluate function is responsible for parsing the OGNL code from the message field. We can see that it checks for either “${“ or “%{“ strings in the message, creates the variable “var,” and evaluates it:

From the following we can see that after processing the entire message, value of var is 1+1, which is taken from the message “Gangster ${1+1} added successfully”:

After the call to evaluate the function is made, the message becomes:

This means the OGNL code we have entered in the name field has been executed internally and is executing 1+1 = 2. Instead of our test input, an attacker could inject malicious OGNL code to launch a new process or download and execute a malicious file, for example.

 

Conclusion

Many OGNL injection vulnerabilities in Apache Struts have been reported. Attackers can take advantage of these vulnerabilities to easily perform malicious activities because exploiting OGNL injection vulnerabilities are relatively simple compared with other attack vectors.

We advise users to update their Apache Struts installations to latest version. Customers of McAfee network intrusion prevention systems are protected from this attack through signature ID 0x45205f00.

Leave a Comment

5 × one =