Critical Vulnerability in Harbor Enables Privilege Escalation from Zero to Admin (CVE-2019-16097)

By

Category: Unit 42

Tags: , , ,

This post is also available in: 日本語 (Japanese)

Executive Summary

Aviv Sasson, a security researcher from the cloud division of Unit 42, has identified a critical vulnerability in a widespread cloud native registry called Harbor. The vulnerability allows attackers to take over Harbor registries by sending them a malicious request.

The maintainers of Harbor released a patch that closes this critical security hole. Versions 1.7.6 and 1.8.3 include this fix.

Unit 42 has found 1,300 Harbor registries open to the internet with vulnerable default settings, which are currently at risk until they’re updated.

Background

As part of our initiative to contribute to and improve Cloud Native Computing Foundation
(CNCF) projects, I recently looked at the Harbor project. I found a critical privilege escalation vulnerability that allows anyone to gain admin permissions under its default settings. The vulnerability had been assigned CVE-2019-16097, which was made public on September 10.

Harbor is an open source cloud native registry that stores, signs and scan images for vulnerabilities. Harbor integrates with Docker Hub, Docker Registry, Google Container Registry and other registries. It provides a simple GUI that allows users to download, upload and scan images according to their permissions.

The Harbor project has been gradually growing in popularity over the last four years and became a CNCF incubating project last November. Harbor includes many notable sponsors and companies within its adopters page.

Figure 1. Officially recognized users and partners of Harbor

Vulnerability Impact

The implications of this vulnerability are serious. There are many attack vectors that can be initiated after gaining admin permissions. The attacker can download all of the private projects and inspect them. They can delete all of the images in the registry or, even worse, poison the registry by replacing its images with their own. The attacker can create a new user and set it to be admin. After that, they can connect to Harbor registry via the Docker command line tool with the new credentials and replace the current images with anything they desire. These can include malware, crypto miners or even worse.

Video 1. Proof of Concept exploitation of the vulnerability

Online Instances

I understood that the problem was severe and wanted to check how many instances are online. In my scan, I found 2,500 Harbors online. I ran a specified script I wrote to assess how many of these instances are vulnerable. The data that I found was that 1,300 registries of those instances are vulnerable.

The Vulnerability

Let’s go over everything. First, let’s examine the ‘User’ struct.

Figure 2. User struct in Harbor source code

The parameter that we want to target is HasAdminRole. It indicates if the user is an admin or not. If we are able to change it into “True”, then we won.

How can we do that?

If we take a look at the API calls, we can see this interesting call that happens if someone tries to access “/api/users”.

Figure 3. /api/users route

If the user sends a POST request, then it will lead to this piece of code that’s in charge of the registration of the new users.

Figure 4. POST request handling logic

The vulnerability is in user.go:317.

if err := ua.DecodeJSONReq(&user); err != nil

In this line of code, we take the data from the post request and decode it into a user object.

A normal request payload will look like this:

{“username”:”test”,”email”:”test123@gmai.com”,”realname”:”no name”,”password”:”Password1\u0021″,”comment”:null}

The problem is that we can send a request and add the parameter “has_admin_role”.

If we send the same request with “has_admin_role” = True, then the user that will be created will be an admin. It’s as simple as that.

Exploitation

I wrote a simple Python script that sends a post request to /api/users in order to create a new user with admin privileges, by setting the “has_admin_role” parameter in the request body to True. After running this script, all we need to do is to open Harbor in the browser and just sign in to the user we created. 

Disclosure Process

While I was assessing this vulnerability’s impact and preparing to responsibly disclose it, the Harbor developers released a commit that includes a fix to this particular vulnerability to the master branch on GitHub. I helped Harbor recognize this is a critical security vulnerability and the CVE assignment. I urged them to publish a new release as fast as possible and their engineers promptly did so.

Mitigation

The Harbor team released the patch to address this issue. The patch went public in a pull request by one of the maintainers, and only later included in Harbor versions 1.7.6 and 1.8.3, which were released on September 18. The release notes mention it resolves the issue with “Disallow creating an admin user when registration”.

The developers added a check that prevents non-admin users from creating a new admin user.

The vulnerability exists in versions 1.7.0 – 1.8.2 and I recommend all users to update their Harbor installations immediately because this vulnerability is critical and gives anyone full access to their registry.

Am I Vulnerable?

If you have a Harbor instance with an out-of-date version, you should take immediate action to update it or at the very least block its connection to the internet. To check if you have been hacked, look for any unrecognized users with admin privileges in your Harbor instance. It’s possible that attackers may have removed the users used in the attack, which would make case detection a more complicated matter — but a spot check at the very least is recommended.