Oracle OpenGrok RCE — CVE-2021–2322

Bobbyr
3 min readJul 29, 2021

--

Introduction

OpenGrok, created by Oracle, is an open source search and cross reference engine. It helps programmers search, cross-reference and navigate source code trees to aid code comprehension. OpenGrok is updated regularly by a community of developers with the help of a few engineers from Oracle (https://github.com/oracle/opengrok/).

After attending Blackhat’s “Web Hacking — Black Belt Edition 2021” training course earlier this year, I decided to search through open source software on Github, to see if I could discover any of the vulnerabilities in the wild, that we had learned about in the course.

I ended up finding OpenGrok, and after careful testing, discovered that OpenGrok insecurely deserializes XML input, which can lead to Remote Code Execution. This vulnerability was found in all versions of OpenGrok <1.6.8 and was reported to Oracle. The vulnerability has now been patched in OpenGrok 1.6.9, and has been issued a CVE. (https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-2322)

Description

OpenGrok supports RESTful API, which allows for authenticated API calls using bearer tokens over an HTTPS connection.

According to the API documentation (https://github.com/oracle/opengrok/blob/master/apiary.apib), an authenticated user can set the OpenGrok configuration via a PUT call to the /api/v1/configuration endpoint.

### sets configuration from XML representation [PUT]

+ Request (application/xml)
+ Body
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_172" class="java.beans.XMLDecoder">
<object class="org.opengrok.indexer.configuration.Configuration" id="Configuration0">
<void property="allowLeadingWildcard">
<boolean>true</boolean>
</void>
</object>
</java>

The /api/v1/configuration endpoint reads the XML and decodes it, without any further validations of its content, or checks of the Java class that is submitted. (https://github.com/jethrogb/OpenGrok/blob/master/src/org/opensolaris/opengrok/configuration/Configuration.java)

private static Configuration decodeObject(InputStream in) throws IOException {

final Object ret;

try (XMLDecoder d = new XMLDecoder(new BufferedInputStream(in))) {

ret = d.readObject();

}

if (!(ret instanceof Configuration)) {

throw new IOException("Not a valid config file");

}

return (Configuration) ret;

}
}

An attacker can submit XML exploit code in the body of a PUT request to the /api/v1/configuration endpoint, utilizing the Java “ProcessBuilder” class to gain Remote Code Execution.

Reproduction Steps

1. An attacker finds a vulnerable OpenGrok instance. The attacker has managed to obtain a valid bearer authentication token, which in this case is “the-token.” The vulnerable instance is hosted on 172.xx.xxx.130

2. The attacker creates a netcat listener on a port. The attacker has an IP address of 172.xx.xxx.129.

3. The attacker writes malicious XML code and saves it in an XML file. This code uses the Java “ProcessBuilder” class to execute the ncat command with the /bin/sh argument on the victim machine, triggering a reverse shell back to the attacker machine which is listening on the specified port. The “ProcessBuilder” class reads and executes a command submitted as a string of a specified length. Each part of the command separated by a space, has to be written as a separate index entry in the Java string.

4. The attacker uses curl to submit the malicious XML code to the /api/v1/configuration endpoint, with a PUT call over HTTPS, and using a valid authentication bearer token as a header.

5. The attacker gains Remote Code Execution, in this case, a Tomcat user-level shell. If OpenGrok was running as a root process on the victim machine, the attacker would gain a root shell.

--

--