hacktricks/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-sandbox/README.md

13 KiB
Raw Blame History

macOS Sandbox

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Basic Information

MacOS Sandbox (initially called Seatbelt) limits applications running inside the sandbox to the allowed actions specified in the Sandbox profile the app is running with. This helps to ensure that the application will be accessing only expected resources.

Any app with the entitlement com.apple.security.app-sandbox will be executed inside the sandbox. Apple binaries are usually executed inside a Sanbox and in order to publish inside the App Store, this entitlement is mandatory. So most applications will be executed inside the sandbox.

In order to control what a process can or cannot do the Sandbox has hooks in all syscalls across the kernel. Depending on the entitlements of the app the Sandbox will allow certain actions.

Some important components of the Sandbox are:

  • The kernel extension /System/Library/Extensions/Sandbox.kext
  • The private framework /System/Library/PrivateFrameworks/AppSandbox.framework
  • A daemon running in userland /usr/libexec/sandboxd
  • The containers ~/Library/Containers

Inside the containers folder you can find a folder for each app executed sanboxed with the name of the bundle id:

ls -l ~/Library/Containers
total 0
drwx------@ 4 username  staff  128 May 23 20:20 com.apple.AMPArtworkAgent
drwx------@ 4 username  staff  128 May 23 20:13 com.apple.AMPDeviceDiscoveryAgent
drwx------@ 4 username  staff  128 Mar 24 18:03 com.apple.AVConference.Diagnostic
drwx------@ 4 username  staff  128 Mar 25 14:14 com.apple.Accessibility-Settings.extension
drwx------@ 4 username  staff  128 Mar 25 14:10 com.apple.ActionKit.BundledIntentHandler
[...]

Inside each bundle id folder you can find the plist and the Data directory of the App:

cd /Users/username/Library/Containers/com.apple.Safari
ls -la
total 104
drwx------@   4 username  staff    128 Mar 24 18:08 .
drwx------  348 username  staff  11136 May 23 20:57 ..
-rw-r--r--    1 username  staff  50214 Mar 24 18:08 .com.apple.containermanagerd.metadata.plist
drwx------   13 username  staff    416 Mar 24 18:05 Data

ls -l Data
total 0
drwxr-xr-x@  8 username  staff   256 Mar 24 18:08 CloudKit
lrwxr-xr-x   1 username  staff    19 Mar 24 18:02 Desktop -> ../../../../Desktop
drwx------   2 username  staff    64 Mar 24 18:02 Documents
lrwxr-xr-x   1 username  staff    21 Mar 24 18:02 Downloads -> ../../../../Downloads
drwx------  35 username  staff  1120 Mar 24 18:08 Library
lrwxr-xr-x   1 username  staff    18 Mar 24 18:02 Movies -> ../../../../Movies
lrwxr-xr-x   1 username  staff    17 Mar 24 18:02 Music -> ../../../../Music
lrwxr-xr-x   1 username  staff    20 Mar 24 18:02 Pictures -> ../../../../Pictures
drwx------   2 username  staff    64 Mar 24 18:02 SystemData
drwx------   2 username  staff    64 Mar 24 18:02 tmp

{% hint style="danger" %} Note that even if the symlinks are there to "escape" from the Sandbox and access other folders, the App still needs to have permissions to access them. These permissions are inside the .plist. {% endhint %}

# Get permissions
plutil -convert xml1 .com.apple.containermanagerd.metadata.plist -o -

# In this file you can find the entitlements:
<key>Entitlements</key>
	<dict>
		<key>com.apple.MobileAsset.PhishingImageClassifier2</key>
		<true/>
		<key>com.apple.accounts.appleaccount.fullaccess</key>
		<true/>
		<key>com.apple.appattest.spi</key>
		<true/>
[...]

# Some parameters
<key>Parameters</key>
	<dict>
		<key>_HOME</key>
		<string>/Users/username</string>
		<key>_UID</key>
		<string>501</string>
		<key>_USER</key>
		<string>username</string>
[...]

# The paths it can access
<key>RedirectablePaths</key>
	<array>
		<string>/Users/username/Downloads</string>
		<string>/Users/username/Documents</string>
		<string>/Users/username/Library/Calendars</string>
		<string>/Users/username/Desktop</string>
[...]

Sandbox Profiles

The Sandbox profiles are configuration files that indicates what is going to be allowed/forbidden in that Sandbox. It uses the Sandbox Profile Language (SBPL), which uses the Scheme programming language.

Here you can find an example:

(version 1) ; First you get the version

(deny default) ; Then you shuold indicate the default action when no rule applies

(allow network*) ; You can use wildcards and allow everything

(allow file-read* ; You can specify where to apply the rule
    (subpath "/Users/username/")
    (literal "/tmp/afile")
    (regex #"^/private/etc/.*")
)

(allow mach-lookup
    (global-name "com.apple.analyticsd")
)

{% hint style="success" %} Check this research to check more actions that could be allowed or denied. {% endhint %}

Important system services also run inside their own custom sandbox such as the mdnsresponder service. You can view these custom sandbox profiles inside:

App Store apps use the profile /System/Library/Sandbox/Profiles/application.sb. You can check in this profile how entitlements such as com.apple.security.network.server allows a process to use the network.

SIP is a Sandbox profile called platform_profile in /System/Library/Sandbox/rootless.conf

Sandbox Profile Examples

To start an application with an specific sandbox profile you can use:

sandbox-exec -f example.sb /Path/To/The/Application

{% tabs %} {% tab title="touch" %} {% code title="touch.sb" %}

(version 1)
(deny default)
(allow file* (literal "/tmp/hacktricks.txt"))

{% endcode %}

# This will fail because default is denied, so it cannot execute touch
sandbox-exec -f touch.sb touch /tmp/hacktricks.txt
# Check logs
log show --style syslog --predicate 'eventMessage contains[c] "sandbox"' --last 30s
[...]
2023-05-26 13:42:44.136082+0200  localhost kernel[0]: (Sandbox) Sandbox: sandbox-exec(41398) deny(1) process-exec* /usr/bin/touch
2023-05-26 13:42:44.136100+0200  localhost kernel[0]: (Sandbox) Sandbox: sandbox-exec(41398) deny(1) file-read-metadata /usr/bin/touch
2023-05-26 13:42:44.136321+0200  localhost kernel[0]: (Sandbox) Sandbox: sandbox-exec(41398) deny(1) file-read-metadata /var
2023-05-26 13:42:52.701382+0200  localhost kernel[0]: (Sandbox) 5 duplicate reports for Sandbox: sandbox-exec(41398) deny(1) file-read-metadata /var
[...]

{% code title="touch2.sb" %}

(version 1)
(deny default)
(allow file* (literal "/tmp/hacktricks.txt"))
(allow process* (literal "/usr/bin/touch"))
; This will also fail because:
; 2023-05-26 13:44:59.840002+0200  localhost kernel[0]: (Sandbox) Sandbox: touch(41575) deny(1) file-read-metadata /usr/bin/touch
; 2023-05-26 13:44:59.840016+0200  localhost kernel[0]: (Sandbox) Sandbox: touch(41575) deny(1) file-read-data /usr/bin/touch
; 2023-05-26 13:44:59.840028+0200  localhost kernel[0]: (Sandbox) Sandbox: touch(41575) deny(1) file-read-data /usr/bin
; 2023-05-26 13:44:59.840034+0200  localhost kernel[0]: (Sandbox) Sandbox: touch(41575) deny(1) file-read-metadata /usr/lib/dyld
; 2023-05-26 13:44:59.840050+0200  localhost kernel[0]: (Sandbox) Sandbox: touch(41575) deny(1) sysctl-read kern.bootargs
; 2023-05-26 13:44:59.840061+0200  localhost kernel[0]: (Sandbox) Sandbox: touch(41575) deny(1) file-read-data /

{% endcode %}

{% code title="touch3.sb" %}

(version 1)
(deny default)
(allow file* (literal "/private/tmp/hacktricks.txt"))
(allow process* (literal "/usr/bin/touch"))
(allow file-read-data (literal "/"))
; This one will work

{% endcode %} {% endtab %} {% endtabs %}

{% hint style="info" %} Note that the Apple-authored software that runs on Windows doesnt have additional security precautions, such as application sandboxing. {% endhint %}

Bypasses examples:

Debug & Bypass Sandbox

Processes are not born sandboxed on macOS: unlike iOS, where the sandbox is applied by the kernel before the first instruction of a program executes, on macOS a process must elect to place itself into the sandbox.

Processes are automatically Sandboxed from userland when they start if they have the entitlement: com.apple.security.app-sandbox. For a detailed explanation of this process check:

{% content-ref url="macos-sandbox-debug-and-bypass/" %} macos-sandbox-debug-and-bypass {% endcontent-ref %}

Check PID Privileges

According to this, the sandbox_check (it's a __mac_syscall), can check if an operation is allowed or not by the sandbox in a certain PID.

The tool sbtool can check if a PID can perform a certain action:

sbtool <pid> mach #Check mac-ports (got from launchd with an api)
sbtool <pid> file /tmp #Check file access
sbtool <pid> inspect #Gives you an explaination of the sandbox profile
sbtool <pid> all

Custom SBPL in App Store apps

It could be possible for companies to make their apps run with custom Sandbox profiles (instead of with the default one). They need to use the entitlement com.apple.security.temporary-exception.sbpl which needs to be authorized by Apple.

It's possible to check the definition of this entitlement in /System/Library/Sandbox/Profiles/application.sb:

(sandbox-array-entitlement
  "com.apple.security.temporary-exception.sbpl"
  (lambda (string)
    (let* ((port (open-input-string string)) (sbpl (read port)))
      (with-transparent-redirection (eval sbpl)))))

This will eval the string after this entitlement as an Sandbox profile.

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥