Bypassing the macOS Gatekeeper

Ron Masas
3 minute read

Timeline

Earlier this year I discovered the wild world of iOS and macOS security.
One of the OBTS conference talks just showed up on my Twitter feed, needless to say, I was hooked.

I was inspired to hunt for this bug by CVE-2021-30657 uncovered by Cedric Owens, and the post All Your Macs Are Belong To Us by Patrick Wardle.

The majority of my career has been focusing on developing and hacking web applications, so as you could imagine I have a lot to learn. This is not going to be a super in-depth write-up, as frankly, I don't currently have the technical skill to truly produce one in a reasonable amount of time - with all of this said, let's get to it!

What is the macOS GateKeeper?

GateKeeper is essentially a series of steps macOS enforces before running a program. The main goal of those steps is to prevent/make it harder for users to infect themselves with malware.

  1. File Quarantine - introduced in 2007, file quarantine provides a warning to the user and requires the user confirmation before execution. For example, when downloading an application from the internet.
  2. "Gatekeeper" - introduced in OSX Lion (10.7), built on top of File Quarantine, Gatekeeper checks the code signing information of downloaded items.
  3. Notarization - introduced in macOS Catalina (10.15), this step ensure that Apple has scanned and approved all software before it is allowed to run.

The bug I've found allowed me to bypass all of those steps, taking your macOS system back to 2006 😉.
Upon clicking the downloaded application (which can be masked as an image or a pdf.) the program would immediately execute, no questions asked.

CVE-2021-30990 proof of concept video

Automator

Automator is your personal automation assistant for creating "automation recipes" in macOS. With Automator, users can create workflows that automate applications, execute scripts, etc.

I've started digging into the application structure, playing with the info.plist and document.wflow files with no much progress.
I was curious about the MacOs binary Automator Application Stub, so I created another application and replaced it's binary with my previous application. I've run my app and it executed just fine confirming that the Automator binaries are interchangeable, they are simply executing the instructions on the document.wflow file.

The Bug

With the realization that the binaries are interchangeable, and that the code executes from the relative document.wflow file, I asked myself the following question, a question that, believe it or not, helped me find dozens of bugs.

What if I put a symlink there?

Turns out the answer to this question is, the application would execute normally. Even with the quarantine attribute, even if it's unsigned.

This means that if an attacker would know the absolute path to a copy of the Automator Application Stub binary on your system, he could craft an application that may bypass all of the Gatekeeper checks.

At this point I thought to myself, this is cool and all, but it would be awesome if a copy of Automator Application Stub would be shipped with macOS at a constant path.
A few find commands later I found that In Big Sur and Monterey, a copy of Automator Application Stub binary can be found at:

/System/Library/CoreServices/Automator Application Stub.app/Contents/MacOS/Automator Application Stub

Making them vulnerable by default.

Steps to reproduce

  1. Open Automator and build a simple Run Shell Script automation.
  2. Export it as an application and run the following commands inside the Contents/MacOS folder of your app.
rm "Automator Application Stub"
ln -s "/System/Library/CoreServices/Automator Application Stub.app/Contents/MacOS/Automator Application Stub" "Automator Application Stub"
  1. Zip your application and your done!

Proof of concept

You can download my proof of concept here

Closing thoughts

I think this vulnerability demonstrates you don't have to be a macOS expert to find bugs. Please don't forget update your macOS systems to Monterey 12.1.

Timeline