# macOS Sandbox {{#include ../../../../banners/hacktricks-training.md}} ## 基本信息 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}` 中拥有自己的容器: ```bash 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 [...] ``` 在每个 bundle id 文件夹内,您可以找到应用的 **plist** 和 **数据目录**,其结构模仿主目录: ```bash 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 ``` > [!CAUTION] > 请注意,即使符号链接存在以“逃离”沙箱并访问其他文件夹,应用程序仍然需要**具有权限**才能访问它们。这些权限在`RedirectablePaths`中的**`.plist`**内。 **`SandboxProfileData`**是编译后的沙箱配置文件CFData,已转义为B64。 ```bash # 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 SandboxProfileData AAAhAboBAAAAAAgAAABZAO4B5AHjBMkEQAUPBSsGPwsgASABHgEgASABHwEf... # In this file you can find the entitlements: Entitlements com.apple.MobileAsset.PhishingImageClassifier2 com.apple.accounts.appleaccount.fullaccess com.apple.appattest.spi keychain-access-groups 6N38VWS5BX.ru.keepcoder.Telegram 6N38VWS5BX.ru.keepcoder.TelegramShare [...] # Some parameters Parameters _HOME /Users/username _UID 501 _USER username [...] # The paths it can access RedirectablePaths /Users/username/Downloads /Users/username/Documents /Users/username/Library/Calendars /Users/username/Desktop RedirectedPaths [...] ``` > [!WARNING] > 由沙盒应用程序创建/修改的所有内容将获得**隔离属性**。如果沙盒应用程序尝试使用**`open`** 执行某些操作,这将通过触发 Gatekeeper 来阻止沙盒空间。 ## 沙盒配置文件 沙盒配置文件是指示在该**沙盒**中将被**允许/禁止**的配置文件。它使用**沙盒配置文件语言 (SBPL)**,该语言使用[**Scheme**]() 编程语言。 这里有一个示例: ```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") ) ``` > [!TIP] > 查看这个 [**研究**](https://reverse.put.as/2011/09/14/apple-sandbox-guide-v1-0/) **以检查更多可能被允许或拒绝的操作。** > > 请注意,在配置文件的编译版本中,操作的名称被其在一个数组中的条目所替代,该数组为dylib和kext所知,使得编译版本更短且更难阅读。 重要的 **系统服务** 也在其自定义 **沙箱** 内运行,例如 `mdnsresponder` 服务。您可以在以下位置查看这些自定义 **沙箱配置文件**: - **`/usr/share/sandbox`** - **`/System/Library/Sandbox/Profiles`** - 其他沙箱配置文件可以在 [https://github.com/s7ephen/OSX-Sandbox--Seatbelt--Profiles](https://github.com/s7ephen/OSX-Sandbox--Seatbelt--Profiles) 中查看。 **App Store** 应用使用 **配置文件** **`/System/Library/Sandbox/Profiles/application.sb`**。您可以在此配置文件中检查诸如 **`com.apple.security.network.server`** 的权限如何允许进程使用网络。 然后,一些 **Apple 守护进程服务** 使用位于 `/System/Library/Sandbox/Profiles/*.sb` 或 `/usr/share/sandbox/*.sb` 的不同配置文件。这些沙箱在调用 API `sandbox_init_XXX` 的主函数中应用。 **SIP** 是一个名为 platform_profile 的沙箱配置文件,位于 `/System/Library/Sandbox/rootless.conf`。 ### 沙箱配置文件示例 要使用 **特定沙箱配置文件** 启动应用程序,您可以使用: ```bash sandbox-exec -f example.sb /Path/To/The/Application ``` {{#tabs}} {{#tab name="touch"}} ```scheme:touch.sb (version 1) (deny default) (allow file* (literal "/tmp/hacktricks.txt")) ``` ```bash # 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 [...] ``` ```scheme: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 / ``` ```scheme: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 ``` {{#endtab}} {{#endtabs}} > [!NOTE] > 请注意,**Apple 编写的** **软件** 在 **Windows** 上 **没有额外的安全措施**,例如应用程序沙箱。 绕过示例: - [https://lapcatsoftware.com/articles/sandbox-escape.html](https://lapcatsoftware.com/articles/sandbox-escape.html) - [https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c](https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c)(他们能够写入以 `~$` 开头的沙箱外部文件)。 ### 沙箱跟踪 #### 通过配置文件 可以跟踪每次检查操作时沙箱执行的所有检查。为此,只需创建以下配置文件: ```scheme:trace.sb (version 1) (trace /tmp/trace.out) ``` 然后只需使用该配置文件执行某些操作: ```bash sandbox-exec -f /tmp/trace.sb /bin/ls ``` 在 `/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**。 如果第三方应用程序携带 _**com.apple.security.app-sandbox**_ 权限,则系统将 **/System/Library/Sandbox/Profiles/application.sb** 配置文件应用于该进程。 在 iOS 中,默认配置文件称为 **container**,我们没有 SBPL 文本表示。在内存中,这个沙箱被表示为每个权限的允许/拒绝二叉树。 ### App Store 应用中的自定义 SBPL 公司可能会使其应用程序 **使用自定义沙箱配置文件**(而不是默认配置文件)。他们需要使用权限 **`com.apple.security.temporary-exception.sbpl`**,该权限需要得到苹果的授权。 可以在 **`/System/Library/Sandbox/Profiles/application.sb:`** 中检查该权限的定义。 ```scheme (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))))) ``` 这将**在此权限之后评估字符串**作为沙箱配置文件。 ### 编译和反编译沙箱配置文件 **`sandbox-exec`** 工具使用 `libsandbox.dylib` 中的 `sandbox_compile_*` 函数。导出的主要函数有:`sandbox_compile_file`(期望文件路径,参数 `-f`),`sandbox_compile_string`(期望字符串,参数 `-p`),`sandbox_compile_name`(期望容器名称,参数 `-n`),`sandbox_compile_entitlements`(期望权限 plist)。 这个反向和[**开源版本的工具 sandbox-exec**](https://newosxbook.com/src.jl?tree=listings&file=/sandbox_exec.c) 允许 **`sandbox-exec`** 将编译的沙箱配置文件写入文件。 此外,为了将进程限制在容器内,它可能会调用 `sandbox_spawnattrs_set[container/profilename]` 并传递一个容器或现有配置文件。 ## 调试和绕过沙箱 在 macOS 上,与 iOS 不同,iOS 中的进程从一开始就被内核沙箱化,**进程必须自行选择进入沙箱**。这意味着在 macOS 上,进程在主动决定进入沙箱之前不会受到沙箱的限制,尽管 App Store 应用始终是沙箱化的。 如果进程具有权限 `com.apple.security.app-sandbox`,则在启动时会自动从用户空间沙箱化。有关此过程的详细说明,请查看: {{#ref}} macos-sandbox-debug-and-bypass/ {{#endref}} ## **沙箱扩展** 扩展允许为对象提供进一步的权限,并通过调用以下函数之一来实现: - `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` 扩展存储在可从进程凭据访问的第二个 MACF 标签槽中。以下 **`sbtool`** 可以访问此信息。 请注意,扩展通常由允许的进程授予,例如,当进程尝试访问照片并在 XPC 消息中被允许时,`tccd` 将授予 `com.apple.tcc.kTCCServicePhotos` 的扩展令牌。然后,进程需要消耗扩展令牌,以便将其添加到其中。\ 请注意,扩展令牌是长十六进制数,编码了授予的权限。然而,它们没有硬编码的允许 PID,这意味着任何可以访问令牌的进程可能会被**多个进程消耗**。 请注意,扩展与权限密切相关,因此拥有某些权限可能会自动授予某些扩展。 ### **检查 PID 权限** [**根据这个**](https://www.youtube.com/watch?v=mG715HcDgO8&t=3011s),**`sandbox_check`** 函数(它是一个 `__mac_syscall`)可以检查**某个 PID、审计令牌或唯一 ID 是否允许某个操作**。 [**工具 sbtool**](http://newosxbook.com/src.jl?tree=listings&file=sbtool.c)(在[这里编译](https://newosxbook.com/articles/hitsb.html))可以检查某个 PID 是否可以执行某些操作: ```bash sbtool mach #Check mac-ports (got from launchd with an api) sbtool file /tmp #Check file access sbtool inspect #Gives you an explanation of the sandbox profile and extensions sbtool all ``` ### \[un]suspend 也可以使用 `libsystem_sandbox.dylib` 中的 `sandbox_suspend` 和 `sandbox_unsuspend` 函数来暂停和恢复沙箱。 请注意,调用暂停函数时会检查一些权限,以授权调用者调用它,例如: - com.apple.private.security.sandbox-manager - com.apple.security.print - com.apple.security.temporary-exception.audio-unit-host ## mac_syscall 此系统调用 (#381) 期望第一个参数为一个字符串,指示要运行的模块,然后第二个参数为一个代码,指示要运行的函数。第三个参数将取决于执行的函数。 函数 `___sandbox_ms` 调用封装了 `mac_syscall`,在第一个参数中指示 `"Sandbox"`,就像 `___sandbox_msp` 是 `mac_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 中,内核扩展包含 **硬编码的所有配置文件**,以避免被修改。以下是内核扩展中的一些有趣函数: - **`hook_policy_init`**: 它挂钩 `mpo_policy_init`,并在 `mac_policy_register` 之后被调用。它执行沙箱的大部分初始化。它还初始化 SIP。 - **`hook_policy_initbsd`**: 它设置 sysctl 接口,注册 `security.mac.sandbox.sentinel`、`security.mac.sandbox.audio_active` 和 `security.mac.sandbox.debug_mode`(如果与 `PE_i_can_has_debugger` 一起引导)。 - **`hook_policy_syscall`**: 它由 `mac_syscall` 调用,第一个参数为 "Sandbox",第二个参数为指示操作的代码。使用 switch 来根据请求的代码查找要运行的代码。 ### MACF Hooks **`Sandbox.kext`** 通过 MACF 使用了超过一百个钩子。大多数钩子只会检查一些微不足道的情况,如果允许执行该操作,则会调用 **`cred_sb_evalutate`**,并传入来自 MACF 的 **凭据** 和一个对应于要执行的 **操作** 的数字,以及一个用于输出的 **缓冲区**。 一个很好的例子是函数 **`_mpo_file_check_mmap`**,它挂钩了 **`mmap`**,并将开始检查新内存是否可写(如果不可写则允许执行),然后检查它是否用于 dyld 共享缓存,如果是,则允许执行,最后调用 **`sb_evaluate_internal`**(或其一个封装)以执行进一步的允许检查。 此外,在沙箱使用的数百个钩子中,有三个特别有趣: - `mpo_proc_check_for`: 如果需要并且之前未应用,则应用配置文件。 - `mpo_vnode_check_exec`: 当进程加载相关二进制文件时调用,然后执行配置文件检查,并检查禁止 SUID/SGID 执行。 - `mpo_cred_label_update_execve`: 当分配标签时调用。这是最长的一个,因为它在二进制文件完全加载但尚未执行时调用。它将执行诸如创建沙箱对象、将沙箱结构附加到 kauth 凭据、移除对 mach 端口的访问等操作。 请注意 **`_cred_sb_evalutate`** 是 **`sb_evaluate_internal`** 的封装,该函数获取传入的凭据,然后使用 **`eval`** 函数执行评估,该函数通常评估默认应用于所有进程的 **平台配置文件**,然后是 **特定进程配置文件**。请注意,平台配置文件是 **SIP** 在 macOS 中的主要组成部分之一。 ## Sandboxd 沙箱还有一个用户守护进程,暴露了 XPC Mach 服务 `com.apple.sandboxd` 并绑定特殊端口 14 (`HOST_SEATBELT_PORT`),内核扩展使用该端口与其通信。它通过 MIG 暴露了一些函数。 ## References - [**\*OS Internals Volume III**](https://newosxbook.com/home.html) {{#include ../../../../banners/hacktricks-training.md}}