Remote Code Execution in Apache Roller via OGNL Injection

Advisory

Overview

From the Roller website

Apache Roller is a full-featured, multi-user and group-blog server suitable for blog sites large and small. It runs as a Java web application that should be able to run on most any Java EE server and relational database.

Roller, starting with version 4, uses Struts2 as its web MVC. Struts2 itself utilizes OGNL as a templating / expression language. The Coverity SRL team previously found a remote code executiion issue in how Struts2 evaluated tainted data via its configuration files. Refer to that blog entry for background on Struts2 and OGNL.

The previous work with Struts2 inspired us to look at potential OGNL "sinks", or locations within the Struts2 framework that evaluate OGNL expressions. We then prototyped an OGNL injection checker internally that tracked tainted data from a Struts2 entry point to these OGNL sinks, utilizing Coverity Security Advisor's custom framework support. We then ran it on a bunch of open source Struts2 applications, which included Roller versions 4 and 5.

Roller version 5 earlier than 5.0.2 and all of version 4 are vulnerable to a pre-authenticated OGNL injection that can result in remote code execution (RCE). The vulnerability is assigned CVE-2013-4212.

Details

One of the OGNL sinks modelled is in the ActionSupport controller via some of its .getText methods. While there are different signatures for these methods, they generally receive a message key and return some type of value usually contained within a resource bundle. (Check out a tutorial by @mkyong if you're interested in how Struts2 resource bundles work.) A couple of these methods, however, pass a parameter to the OGNL evaluator. Here is a list of ActionSupport methods where either the first or second parameter is evaluated as OGNL:

(Note: there are many, many more Struts2 methods similar to the above that evaluate OGNL.)

Roller uses some of these affected methods in its UIAction controller, wrapped via the .addError and .addMessage methods. These utility methods are called via a variety of subclasses, some of which passed tainted data to the methods. Any of these controllers could be used to attack Roller and execute code remotely via OGNL injection.

There's a specific interesting case of OGNL injection in Roller. Before diving into the details below, take a look at this article on Dynamic Method Invocation (DMI).

Going back to UIAction, it also has a .getPageTitle() method that calls ActionSupport.getText(java.lang.String):

    public String getPageTitle() {
        return getText(pageTitle);
    }

Again, the .getText method is an OGNL sink. Since Roller enables DMI, this method is exposed on all subclasses of UIAction. Right below that method is the setter:

    public void setPageTitle(String pageTitle) {
        this.pageTitle = pageTitle;
    }

The sub-URL !getPageTitle?pageTitle=OGNL_HERE executes arbitrary OGNL on any subclasses of UIAction. One interesting subclass that's exposed pre-authentication is org.apache.roller.weblogger.ui.struts2.core.Login, via /roller-ui/login.rol URI. (Roller uses the .rol suffix for Struts2 instead of the .do convention.)

Remedy

Apache Roller recommends all users upgrade to 5.0.2 to rememdy the above issues.

Other advisories