Post

CVE-2021-43269

Introduction

Recently I’ve had an opportunity to spend some time testing something different than I’m used to - a desktop application. The desktop application I picked was interesting to me because of two reasons:

  • It was written in Java, so I could’ve easily decompiled it to readable code
  • Some of its functions were run with root privileges on the local system

I thought, if I could find a bug that allowed me to run code, it would run with root permissions, which would lead to a significant impact. During the testing, I learned a lot and found multiple interesting issues. In this post, I want to present my root-level remote code execution (RCE) finding which was assigned CVE-2021-43269 ID, and the steps I took to find it.

Application description

Code42 is a company that offers a product to protect companies from ransomware and insider data exfiltration attacks. Its main product uses a desktop application run on every computer in the organization. The application connects to either an on-premise server, or a server in the cloud, and performs scheduled backups of important files, scans files for malicious content, and inspects the computer for data exfiltration, like sending sensitive files to a flash drive.

On a Linux system, the desktop application can be installed per user and then runs with given user permissions, or it can be installed system-wide, and run with root-level permissions. This solution is at the same time dangerous, but is understandable because otherwise it would be difficult for the main process to control sensitive system files and actions.

The company split the application into two separate parts - the main part, called Service, runs as root doing all the heavy work, and the UI part allows the user to change settings, or select which files he wants to back up. This solution implements a layer of protection because a low-privilege user cannot gain root privileges of the Service process without a bug inside it.

Unpacking the application code

After installing the application, and reviewing its file structure I gained slight knowledge about what technologies it uses. I concluded that the main Service part is written in Java with a small binary wrapper, which is used to add arguments to the JAR file execution. The Client application is written in Electron, but apart from describing how I unpacked the app.asar file, I am not focusing on it in this post.

Client application

To decompile the client part I’ve used the NPM tool called asar. Its usage is very simple, all I had to do was to install it using NPM:

1
npm install -g asar

Use it to extract app.asar file from electron/resources directory under the installation folder:

1
asar extract /usr/local/crashplan/electron/resources/app.asar <extraction destination directory>

The asar application extracted bundled Electron application to the destination directory, and I could analyze its content. Unfortunately, the most important part of the application was minified, so it was not too easy to read it. Fortunately, some parts of the source code were readable. Thanks to that I have found an argument to enable debug options, which helped to see how the client application communicates with the Service process.

Service application

To decompile the Service application written in Java, I used a tool called jd-cli and created a simple bash loop to decompile all libraries connected to the Code42 application. Firstly I’ve downloaded jd-cli from GitHub, and built it using maven:

1
2
git clone https://github.com/intoolswetrust/jd-cli
cd jd-cli && mvn clean install

after successful build, I’ve written simple loop to unpack and decompile all interesting libraries:

1
2
3
4
5
6
7
8
9
10
11
mkdir classes sources
for f in /usr/local/crashplan/lib/*c*42*; do
	basename=$(basename $f)
	filename="${basename&.*}"
	
	mkdir ./classes/$filename && cd ./classes/$filename
	jar -xvf $f
	
	cd ../../
	java -jar <path to jd-cli.jar> -od ./sources/$filename ./classes/$filename
done

This script creates classes and sources directory, unpacks classes from the JAR file, and decompiles them into the sources directory.

After running this script I had all interesting libraries unpacked in a readable format ready to be analyzed using a code editor. It was now time to analyze how the system work.

Code execution via Proxy PAC file

Description

While exploring the functionalities of the application I spent some time playing with the proxy settings. My goal was to connect the Burp Suite proxy to the application and check what network traffic it generates. Proxy in Code42 application is configured using PAC files with necessary configuration settings put inside it. The file can be downloaded by the application from the external server or a local file located on the disk. I have looked on the internet for a sample PAC file to properly attach it to Burp, and as result created a file with the following content:

1
2
3
4
function FindProxyForURL(url, host) 
{ 
	return "PROXY 127.0.0.1:8080"; 
}

For some reason (probably certificate issues) it did not work, and I did not receive any requests in Burp. I started to investigate the issue further, changed PAC file content, and checked application logs, and inside them, I’ve noticed an interesting error message saying:

Error while executing PAC script:
ReferenceError: "aaa" is not defined in <eval> at line number 6

When I noticed the keyword eval it scratched the “it looks suspicious, let’s break it!” part of my brain. I quickly started to search source code for the proxy file evaluation function, and I found that the application is using the Nashorn engine to parse and execute PAC file content as a Javascript code. A quick google search for vulnerabilities in the Nashorn engine pointed me to this article: https://mbechler.github.io/2019/03/02/Beware-the-Nashorn/.

The article helped me to create a simple proof of concept file to execute arbitrary code on the root level:

1
2
3
4
5
6
this.engine.factory.scriptEngine.eval('java.lang.Runtime.getRuntime().exec("touch /tmp/test.txt")'); 

function FindProxyForURL(url, host) 
{ 
	return "DIRECT"; 
}

This vulnerability uses an issue in the Nashorn engine default configuration, which according to the author of the article, Oracle says is intended behavior. The above script, when loaded by the application and passed to the Nashorn engine got the global engine variable, created a fresh scripting engine with default, insecure configuration, and executed malicious Javascript code with access to the Java functions. In this example, it uses the Java Runtime method to execute system commands.

I changed the application configuration to use my exploit file as a proxy configuration and, after loading it, the test.txt file was created in the /tmp directory, which proved the Java code gets executed. The newly created file was owned by the root user, which indicated that the code was run with root-level permissions increasing the severity of this bug.

Exploitation

This vulnerability could be used by both, local and external attackers. The local low-privileged user could use it to increase his privileges to root, and as result get full control of the system. For the external attacker, there are a few other exploitation possibilities:

  • The attacker could obtain access to the online administration panel (by for example phishing attack), and change proxy settings in each computer in the organization, which would give him root-level code execution in the whole organization
  • The attacker could social engineer the victim user to set proxy settings to an external link provided by the attacker. The link would point to the malicious proxy configuration file, and when downloaded and evaluated by the application, it would run malicious code as a root user
  • If a company provided proxy configuration files in for example unprotected S3 bucket, a malicious attacker could overwrite its content, and get root code execution in all computers in the organization

This issue was assigned P1 severity on Bugcrowd and was my very first P1 issue in the bug bounty world.

This post is licensed under CC BY 4.0 by the author.