Recently I read a really good book about macOS #appsec - Professional Cocoa Application Security. It’s from 2010 but still worth reading as the main concepts didn’t change so much. In this blog post, I’d like to share an interesting story that led to the discovery of
CVE-2021-3162 - a local privilege escalation vulnerability in Docker on macOS.
In Chapter 10 - “Deploying Software Securely”, I stumbled across configuring XPC services installers. As you maybe know, I created a secure XPC service example, so I researched that topic very deeply. In order to install an XPC server (aka Privileged Helper), the host applications should use SMJobBless API. The host app needs to specify a code requirement in their
Info.plist file. When the
SMJobBless() function is called, macOS will verify if the helper (that’s going to be installed) meets that code requirement. That’s a very important step because, without it, a malicious application may just replace another app’s helper and wait until it is installed. As the privileged helpers are installed as root, such a situation would lead to local privilege escalation attacks.
Books can be wrong too
So, let’s take a look at the
Info.plist file example included in Chapter 10:
Can you spot the vulnerability? If not, see the Apple’s docs:
SMPrivilegedExecutables key doesn’t specify the
anchor apple generic requirement. It means that I can just generate my certificate using OpenSSL (or any other tool) and meet that requirement!
When I read that faulty example, I immediately verified if my installed applications don’t implement the same mistake. It turned out that I had one installed - Docker Community:
In order to write an exploit for that, I had to make sure if the Docker is installed with my user’s permissions. To be more accurate, the
/Applications/Docker.app must be writable by my user because we need to alter the helper. I verified that the directory is writable, so there is an LPE opportunity. Docker is installed with a Drag&Drop method, so since you are the user who actually drags the application and drops it in the
/Applications, it is copied with your privileges (if you are in the admin group, of course).
I showed in one of my previous blog posts how to generate a custom certificate and sign a bundle; I won’t repeat it in this post. If you’d like to reproduce it, just follow the following steps:
- Install old Docker (<220.127.116.11)
- Create a malicious helper (remember about embedded launchd.plist and info.plist)
- Alter the Docker’s helper
- Run Docker and make it install the helper
- Great, you have a service running as root :-)
Now Docker uses the
anchor apple generic requirement:
This vulnerability has been fixed in version 18.104.22.168. CVE-2021-3162 has been assigned. The exploitation conditions are not trivial, but I think it’s a worth sharing story. 😉