macOS Sandbox

Support HackTricks

基本情報

MacOS Sandbox(最初はSeatbeltと呼ばれていた)は、サンドボックス内で実行されるアプリケーションを、アプリが実行されているサンドボックスプロファイルで指定された許可されたアクションに制限します。これにより、アプリケーションが予期されるリソースのみをアクセスすることが保証されます

com.apple.security.app-sandboxの権限を持つアプリは、サンドボックス内で実行されます。Appleのバイナリは通常サンドボックス内で実行され、App Storeのすべてのアプリケーションはその権限を持っています。したがって、いくつかのアプリケーションはサンドボックス内で実行されます。

プロセスが何をできるか、またはできないかを制御するために、サンドボックスはほぼすべての操作にフックを持っています(ほとんどのシステムコールを含む)MACFを使用しています。しかし、アプリの権限に応じて、サンドボックスはプロセスに対してより許可的になる場合があります。

サンドボックスのいくつかの重要なコンポーネントは次のとおりです:

  • カーネル拡張 /System/Library/Extensions/Sandbox.kext

  • プライベートフレームワーク /System/Library/PrivateFrameworks/AppSandbox.framework

  • ユーザーランドで実行されるデーモン /usr/libexec/sandboxd

  • コンテナ ~/Library/Containers

コンテナ

すべてのサンドボックス化されたアプリケーションは、~/Library/Containers/{CFBundleIdentifier}に独自のコンテナを持ちます:

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
[...]

各バンドルIDフォルダー内には、plistとアプリのデータディレクトリがあり、ホームフォルダーを模した構造になっています:

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

注意してください。シンボリックリンクがSandboxから「脱出」して他のフォルダにアクセスするために存在していても、アプリはそれらにアクセスするための権限を持っている必要があります。これらの権限は、RedirectablePathsの**.plist**の中にあります。

**SandboxProfileData**は、B64にエスケープされたコンパイル済みのサンドボックスプロファイルCFDataです。

# Get container config
## You need FDA to access the file, not even just root can read it
plutil -convert xml1 .com.apple.containermanagerd.metadata.plist -o -

# Binary sandbox profile
<key>SandboxProfileData</key>
<data>
AAAhAboBAAAAAAgAAABZAO4B5AHjBMkEQAUPBSsGPwsgASABHgEgASABHwEf...

# 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/>
<key>keychain-access-groups</key>
<array>
<string>6N38VWS5BX.ru.keepcoder.Telegram</string>
<string>6N38VWS5BX.ru.keepcoder.TelegramShare</string>
</array>
[...]

# 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>
<key>RedirectedPaths</key>
<array/>
[...]

Sandboxedアプリケーションによって作成/変更されたすべてのものには隔離属性が付与されます。これにより、サンドボックスアプリが**open**を使用して何かを実行しようとした場合に、Gatekeeperがトリガーされてサンドボックス空間が防止されます。

サンドボックスプロファイル

サンドボックスプロファイルは、そのサンドボックスで何が許可/禁止されるかを示す設定ファイルです。これは**サンドボックスプロファイル言語(SBPL)**を使用し、Schemeプログラミング言語を利用しています。

ここに例があります:

(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")
)

この研究を確認して、許可または拒否される可能性のある他のアクションを確認してください。

プロファイルのコンパイルされたバージョンでは、操作の名前がdylibおよびkextによって知られている配列のエントリに置き換えられ、コンパイルされたバージョンが短く、読みづらくなります。

重要なシステムサービスも、mdnsresponderサービスのように独自のカスタムサンドボックス内で実行されます。これらのカスタムサンドボックスプロファイルは以下で確認できます:

App Storeアプリは**プロファイル****/System/Library/Sandbox/Profiles/application.sbを使用します。このプロファイルで、com.apple.security.network.server**のような権限がプロセスにネットワークを使用することを許可する方法を確認できます。

SIPは、/System/Library/Sandbox/rootless.confにあるplatform_profileというサンドボックスプロファイルです。

サンドボックスプロファイルの例

特定のサンドボックスプロファイルでアプリケーションを起動するには、次のようにします:

sandbox-exec -f example.sb /Path/To/The/Application
touch.sb
(version 1)
(deny default)
(allow file* (literal "/tmp/hacktricks.txt"))
# 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
[...]
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 /
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

Appleが作成した ソフトウェアは、Windows上で追加のセキュリティ対策、例えばアプリケーションサンドボックスがありません。

バイパスの例:

サンドボックストレース

プロファイル経由

アクションがチェックされるたびにサンドボックスが実行するすべてのチェックをトレースすることが可能です。そのためには、次のプロファイルを作成します:

trace.sb
(version 1)
(trace /tmp/trace.out)

その後、そのプロファイルを使用して何かを実行します:

sandbox-exec -f /tmp/trace.sb /bin/ls

In /tmp/trace.out では、呼び出されるたびに実行される各サンドボックスチェックを見ることができます(つまり、多くの重複があります)。

-t パラメータを使用してサンドボックスをトレースすることも可能です: sandbox-exec -t /path/trace.out -p "(version 1)" /bin/ls

API経由

libsystem_sandbox.dylib にエクスポートされている関数 sandbox_set_trace_path は、サンドボックスチェックが書き込まれるトレースファイル名を指定することを可能にします。 また、sandbox_vtrace_enable() を呼び出し、その後 sandbox_vtrace_report() を呼び出してバッファからログエラーを取得することでも同様のことが可能です。

サンドボックス検査

libsandbox.dylib は、プロセスのサンドボックス状態のリスト(拡張を含む)を提供する sandbox_inspect_pid という関数をエクスポートしています。ただし、この関数はプラットフォームバイナリのみが使用できます。

MacOS & iOS サンドボックスプロファイル

MacOS は、システムサンドボックスプロファイルを /usr/share/sandbox//System/Library/Sandbox/Profiles の2つの場所に保存します。

サードパーティアプリケーションが com.apple.security.app-sandbox 権限を持っている場合、システムはそのプロセスに /System/Library/Sandbox/Profiles/application.sb プロファイルを適用します。

iOS では、デフォルトプロファイルは container と呼ばれ、SBPL テキスト表現はありません。メモリ内では、このサンドボックスはサンドボックスからの各権限のための許可/拒否バイナリツリーとして表現されます。

App Store アプリのカスタム SBPL

企業がアプリを カスタムサンドボックスプロファイル で実行することが可能な場合があります(デフォルトのものではなく)。彼らは com.apple.security.temporary-exception.sbpl 権限を使用する必要があり、これは Apple によって承認される必要があります。

この権限の定義は /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.

Compiling & decompiling a Sandbox Profile

The sandbox-exec tool uses the functions sandbox_compile_* from libsandbox.dylib. The main functions exported are: sandbox_compile_file (expects a file path, param -f), sandbox_compile_string (expects a string, param -p), sandbox_compile_name (expects a name of a container, param -n), sandbox_compile_entitlements (expects entitlements plist).

This reversed and open sourced version of the tool sandbox-exec allows to make sandbox-exec write into a file the compiled sandbox profile.

Moreover, to confine a process inside a container it might call sandbox_spawnattrs_set[container/profilename] and pass a container or pre-existing profile.

Debug & Bypass Sandbox

On macOS, unlike iOS where processes are sandboxed from the start by the kernel, processes must opt-in to the sandbox themselves. This means on macOS, a process is not restricted by the sandbox until it actively decides to enter it, although App Store apps are always sandboxed.

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:

macOS Sandbox Debug & Bypass

Sandbox Extensions

Extensions allow to give further privileges to an object and are giving calling one of the functions:

  • sandbox_issue_extension

  • sandbox_extension_issue_file[_with_new_type]

  • sandbox_extension_issue_mach

  • sandbox_extension_issue_iokit_user_client_class

  • sandbox_extension_issue_iokit_registry_rentry_class

  • sandbox_extension_issue_generic

  • sandbox_extension_issue_posix_ipc

The extensions are stored in the second MACF label slot accessible from the process credentials. The following sbtool can access this information.

Note that extensions are usually granted by allowed processes, for example, tccd will grant the extension token of com.apple.tcc.kTCCServicePhotos when a process tried to access the photos and was allowed in a XPC message. Then, the process will need to consume the extension token so it gets added to it. Note that the extension tokens are long hexadecimals that encode the granted permissions. However they don't have the allowed PID hardcoded which means that any process with access to the token might be consumed by multiple processes.

Note that extensions are very related to entitlements also, so having certain entitlements might automatically grant certain extensions.

Check PID Privileges

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

The tool sbtool (find it compiled here) can check if a PID can perform a certain actions:

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 explanation of the sandbox profile and extensions
sbtool <pid> all

[un]suspend

サンドボックスを一時停止および再開することも可能で、libsystem_sandbox.dylibsandbox_suspendおよびsandbox_unsuspend関数を使用します。

一時停止関数を呼び出すには、以下のように呼び出し元を認可するためにいくつかの権限がチェックされることに注意してください。

  • com.apple.private.security.sandbox-manager

  • com.apple.security.print

  • com.apple.security.temporary-exception.audio-unit-host

mac_syscall

このシステムコール(#381)は、最初の引数としてモジュールを示す文字列を期待し、次の引数には実行する関数を示すコードを指定します。3番目の引数は実行される関数に依存します。

関数___sandbox_ms呼び出しは、最初の引数に"Sandbox"を指定してmac_syscallをラップし、___sandbox_mspmac_set_proc(#387)のラッパーです。次に、___sandbox_msによってサポートされているコードの一部は、次の表に示されています。

  • set_profile (#0): プロセスにコンパイル済みまたは名前付きプロファイルを適用します。

  • platform_policy (#1): プラットフォーム固有のポリシーチェックを強制します(macOSとiOSで異なります)。

  • check_sandbox (#2): 特定のサンドボックス操作の手動チェックを実行します。

  • note (#3): サンドボックスに注釈を追加します。

  • container (#4): 通常はデバッグまたは識別のために、サンドボックスに注釈を添付します。

  • extension_issue (#5): プロセスの新しい拡張を生成します。

  • extension_consume (#6): 指定された拡張を消費します。

  • extension_release (#7): 消費された拡張に関連付けられたメモリを解放します。

  • extension_update_file (#8): サンドボックス内の既存のファイル拡張のパラメータを変更します。

  • extension_twiddle (#9): 既存のファイル拡張を調整または変更します(例:TextEdit、rtf、rtfd)。

  • suspend (#10): すべてのサンドボックスチェックを一時的に停止します(適切な権限が必要です)。

  • unsuspend (#11): 以前に一時停止されたすべてのサンドボックスチェックを再開します。

  • passthrough_access (#12): サンドボックスチェックをバイパスしてリソースへの直接パススルーアクセスを許可します。

  • set_container_path (#13): (iOSのみ)アプリグループまたは署名IDのためのコンテナパスを設定します。

  • container_map (#14): (iOSのみ)containermanagerdからコンテナパスを取得します。

  • sandbox_user_state_item_buffer_send (#15): (iOS 10+)サンドボックス内のユーザーモードメタデータを設定します。

  • inspect (#16): サンドボックス化されたプロセスに関するデバッグ情報を提供します。

  • dump (#18): (macOS 11)分析のためにサンドボックスの現在のプロファイルをダンプします。

  • vtrace (#19): 監視またはデバッグのためにサンドボックス操作をトレースします。

  • builtin_profile_deactivate (#20): (macOS < 11)名前付きプロファイルを無効にします(例:pe_i_can_has_debugger)。

  • check_bulk (#21): 単一の呼び出しで複数のsandbox_check操作を実行します。

  • reference_retain_by_audit_token (#28): サンドボックスチェックで使用するための監査トークンの参照を作成します。

  • reference_release (#29): 以前に保持された監査トークン参照を解放します。

  • rootless_allows_task_for_pid (#30): task_for_pidが許可されているかどうかを確認します(csrチェックに類似)。

  • rootless_whitelist_push (#31): (macOS)システム整合性保護(SIP)マニフェストファイルを適用します。

  • rootless_whitelist_check (preflight) (#32): 実行前にSIPマニフェストファイルをチェックします。

  • rootless_protected_volume (#33): (macOS)ディスクまたはパーティションにSIP保護を適用します。

  • rootless_mkdir_protected (#34): ディレクトリ作成プロセスにSIP/DataVault保護を適用します。

Sandbox.kext

iOSでは、カーネル拡張が__TEXT.__constセグメント内にすべてのプロファイルをハードコーディングしているため、変更されないようにしています。以下はカーネル拡張からのいくつかの興味深い関数です。

  • hook_policy_init: mpo_policy_initをフックし、mac_policy_registerの後に呼び出されます。サンドボックスの初期化のほとんどを実行します。また、SIPも初期化します。

  • hook_policy_initbsd: security.mac.sandbox.sentinelsecurity.mac.sandbox.audio_active、およびsecurity.mac.sandbox.debug_modeを登録するsysctlインターフェースを設定します(PE_i_can_has_debuggerでブートされた場合)。

  • hook_policy_syscall: "Sandbox"を最初の引数として、操作を示すコードを2番目の引数としてmac_syscallによって呼び出されます。スイッチを使用して、要求されたコードに応じて実行するコードを見つけます。

MACF Hooks

Sandbox.kextは、MACFを介して100以上のフックを使用します。ほとんどのフックは、アクションを実行できるかどうかを確認するための些細なケースをチェックし、そうでない場合はcred_sb_evalutateを呼び出し、資格情報と操作に対応する番号、そして出力用のバッファを渡します。

その良い例が、フックされた**_mpo_file_check_mmap関数で、これはmmapをフックし、新しいメモリが書き込み可能かどうかをチェックし(そうでない場合は実行を許可し)、次にそれがdyld共有キャッシュに使用されているかどうかをチェックし、そうであれば実行を許可し、最後にsb_evaluate_internal**(またはそのラッパーの1つ)を呼び出してさらなる許可チェックを実行します。

さらに、サンドボックスが使用する100以上のフックの中で、特に興味深い3つがあります。

  • mpo_proc_check_for: 必要に応じてプロファイルを適用し、以前に適用されていない場合。

  • mpo_vnode_check_exec: プロセスが関連するバイナリをロードするときに呼び出され、プロファイルチェックとSUID/SGID実行を禁止するチェックが行われます。

  • mpo_cred_label_update_execve: ラベルが割り当てられるときに呼び出されます。これは、バイナリが完全にロードされるがまだ実行されていないときに呼び出されるため、最も長いものです。サンドボックスオブジェクトの作成、kauth資格情報へのサンドボックス構造の添付、machポートへのアクセスの削除などのアクションを実行します。

_cred_sb_evalutatesb_evaluate_internalのラッパーであり、この関数は渡された資格情報を取得し、次にeval関数を使用して評価を実行します。この関数は通常、すべてのプロセスにデフォルトで適用されるプラットフォームプロファイルを評価し、その後特定のプロセスプロファイルを評価します。プラットフォームプロファイルは、macOSのSIPの主要なコンポーネントの1つです。

Sandboxd

サンドボックスには、XPC Machサービスcom.apple.sandboxdを公開し、カーネル拡張が通信に使用する特別なポート14(HOST_SEATBELT_PORT)をバインドするユーザーデーモンもあります。MIGを使用していくつかの関数を公開します。

References

Support HackTricks

Last updated