macOS Sandbox
Basic Information
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
Containers
每个沙箱应用程序将在 ~/Library/Containers/{CFBundleIdentifier}
中拥有自己的容器:
在每个 bundle id 文件夹内,您可以找到应用的 plist 和 数据目录,其结构模仿主文件夹:
请注意,即使符号链接存在以“逃离”沙盒并访问其他文件夹,应用程序仍然需要拥有权限才能访问它们。这些权限在RedirectablePaths
中的**.plist
**内。
**SandboxProfileData
**是编译后的沙盒配置文件CFData,已转义为B64。
由沙盒应用程序创建/修改的所有内容将获得隔离属性。这将通过触发Gatekeeper来防止沙盒空间,如果沙盒应用程序尝试使用**open
**执行某些操作。
沙盒配置文件
沙盒配置文件是指示在该沙盒中将被允许/禁止的配置文件。它使用沙盒配置文件语言(SBPL),该语言使用Scheme编程语言。
这里是一个示例:
查看这个 研究 以检查更多可以被允许或拒绝的操作。
请注意,在配置文件的编译版本中,操作的名称被其在一个数组中的条目所替代,该数组为dylib和kext所知,使得编译版本更短且更难以阅读。
重要的 系统服务 也在其自定义 沙箱 内运行,例如 mdnsresponder
服务。您可以在以下位置查看这些自定义 沙箱配置文件:
/usr/share/sandbox
/System/Library/Sandbox/Profiles
其他沙箱配置文件可以在 https://github.com/s7ephen/OSX-Sandbox--Seatbelt--Profiles 中查看。
App Store 应用使用 配置文件 /System/Library/Sandbox/Profiles/application.sb
。您可以在此配置文件中检查诸如 com.apple.security.network.server
的权限如何允许进程使用网络。
SIP 是一个名为 platform_profile 的沙箱配置文件,位于 /System/Library/Sandbox/rootless.conf
沙箱配置文件示例
要使用 特定沙箱配置文件 启动应用程序,您可以使用:
请注意,Apple 编写的 软件 在 Windows 上 没有额外的安全措施,例如应用程序沙箱。
绕过示例:
https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c (他们能够写入以
~$
开头的沙箱外文件)。
沙箱跟踪
通过配置文件
可以跟踪每次检查操作时沙箱执行的所有检查。为此,只需创建以下配置文件:
然后只需使用该配置文件执行某些操作:
在 /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:
中检查此权限的定义。
这将在此权限之后评估字符串作为沙箱配置文件。
编译和反编译沙箱配置文件
sandbox-exec
工具使用 libsandbox.dylib
中的 sandbox_compile_*
函数。导出的主要函数有:sandbox_compile_file
(期望文件路径,参数 -f
),sandbox_compile_string
(期望字符串,参数 -p
),sandbox_compile_name
(期望容器名称,参数 -n
),sandbox_compile_entitlements
(期望权限 plist)。
这个反向和开源版本的工具 sandbox-exec 允许 sandbox-exec
将编译的沙箱配置文件写入文件。
此外,为了将进程限制在容器内,它可能会调用 sandbox_spawnattrs_set[container/profilename]
并传递一个容器或预先存在的配置文件。
调试和绕过沙箱
在 macOS 上,与 iOS 不同,iOS 中的进程从一开始就被内核沙箱化,进程必须自行选择进入沙箱。这意味着在 macOS 上,进程在主动决定进入沙箱之前不会受到沙箱的限制,尽管 App Store 应用始终是沙箱化的。
如果进程具有权限 com.apple.security.app-sandbox
,则在启动时会自动从用户空间沙箱化。有关此过程的详细说明,请查看:
沙箱扩展
扩展允许为对象提供进一步的权限,并通过调用以下函数之一来实现:
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 权限
根据这个,sandbox_check
函数(它是一个 __mac_syscall
)可以检查某个 PID、审计令牌或唯一 ID 是否允许某个操作。
工具 sbtool(在这里找到编译版本)可以检查某个 PID 是否可以执行某些操作:
[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
Last updated