Background

Recently the F5 security research team has witnessed a series of CVE’s created for the popular Apache Struts platform.

From Wikipedia:
Apache Struts was an open-source web application framework for developing Java EE web applications. It uses and extends the Java Servlet API to encourage developers to adopt a model–view–controller (MVC) architecture. It was originally created by Craig McClanahan and donated to the Apache Foundation in May, 2000. Formerly located under the Apache Jakarta Project and known as Jakarta Struts, it became a top-level Apache project in 2005.

The initial CVE-2014-0094 disclosed a critical vulnerability that allows an attacker to manipulate ClassLoader by using the ‘class’ parameter, which is directly mapped to the getClass() method through the ParametersInterceptor module in the Struts framework.

The Apache Struts security bulletin recommended upgrading to Struts 2.3.16.1 to mitigate the vulnerability.
Alternatively, users were also able to mitigate this vulnerability using a configuration change on their current Struts installations.

The mitigation included adding the following regular expression to the list of disallowed parameters in ParametersInterceptor:

'^class\.*'

 

After several weeks, the solution was found to be incomplete, and sparked four new CVE’s: CVE-2014-0112, CVE-2014-0113, CVE-2014-0114 and CVE-2014-0116.
Note: During the initial release of this article, CVE-2014-0114 and CVE-2014-0116 were not yet publicly disclosed, and weren't mentioned in this article.
The article has now been edited to include mitigation for these CVEs as well.

CVE-2014-0112 mentions the ClassLoader vulnerability still existing in parameters, and the security advisory for it suggests a new regular expression to include in the ParametersInterceptor config:

(.*\.|^|.*|\[('|"))class(\.|('|")]|\[).*

 

This new regex hints that the previous regex was not tight enough, and was able to be bypassed using other permutations of the class parameters, such as:
http://example.com/?class[“name”]
http://example.com/?object[“class”]
http://example.com/?object[‘class’]

CVE-2014-0113 mentions the ClassLoader still existing in the CookieInterceptor module.
This particular security advisory allows no solution for installations which already accept cookies using a wildcard.

CVE-2014-0114 mentions the same vulnerability in parameters, similar to CVE-2014-0112, only for older versions of Apache Struts (1.x through 1.3.10).

CVE-2014-0116 fixes CVE-2014-0113 by applying the same negative pattern to CookieInterceptor configuration.

An ASM based solution

Using ASM we are able to deliver an immediate response to mitigate these CVEs.

The solution is based on signatures which will block requests that match what a malicious attack should look like.

The user-defined signature is as such:

valuecontent:"class"; norm; nocase; re2:"/(?:\bclass[.\[]|\[\x22class\x22\]|\['class'\])/Vi"; norm;

 

The signature attempts to find parameters which contain one of the following case-insensitive strings:

  • class.
  • [“class”]
  • [‘class’]
  • class[

For versions 11.4.0 and up, this signature will mitigate all CVEs (CVE-2014-0112, CVE-2014-0113, CVE-2014-0114 and CVE-2014-0116).
This is thanks to cookies being parsed as parameters in those versions.

In versions prior to 11.4.0, this signature will mitigate only CVE-2014-0112 and CVE-2014-0114.
A separate signature is required to mitigate CVE-2014-0113 and CVE-2014-0116.
Please see the Appendix for specific rules.

Note: These signatures should be treated as a temporary solution.
A final updated signature will be included in the next Attack Signature Update after the issue will have been further investigated.

Note: The current signature may lead to false positives for customers who use parameters which include the “class” keyword in their name.
The safe solution would be upgrading to Apache Struts 2.3.16.3, as recommended in the official security advisory.

References

https://cwiki.apache.org/confluence/display/WW/S2-021

Appendix

Signatures for BIG-IP versions 11.2.0 until 11.3.0 (incl.):

valuecontent:"class"; norm; nocase; re2:"/(?:\bclass[.\[]|\[\x22class\x22\]|\['class'\])/Vi"; norm;
headercontent:"class"; nocase; re2:"/Cookie:.*?(?:\bclass[.\[]|\bclass\[|\[\x22class\x22\]|\['class'\])/Hi";

 

Signatures for BIG-IP versions 10.1.0 until 11.1.0 (incl.):

valuecontent:"class"; norm; nocase; pcre:"/(?:\bclass[.\[]|\[\x22class\x22\]|\['class'\])/Vi"; norm;
headercontent:"class"; nocase; pcre:"/Cookie:.*?(?:\bclass[.\[]|\bclass\[|\[\x22class\x22\]|\['class'\])/Hi";