Protect your Mac app with environment constraints
System & Services 进阶 20m

用环境约束保护你的 Mac app

Protect your Mac app with environment constraints

2023年6月5日

在 Apple 官方观看视频

一句话判断

Environment Constraints 是 macOS Sonoma 引入的新安全层,控制你的进程在什么条件下才能运行以及加载什么代码。

这场 Session 讲了什么

macOS Sonoma 引入了 Environment Constraints(环境约束),这是一种描述代码预期运行方式的新机制。它允许开发者控制进程的运行条件和进程中可以混合的代码。

环境约束有三种类型。Launch Constraints(启动约束)嵌入到特定二进制文件中,定义进程自身的属性、父进程属性和负责进程属性。Library Load Constraints(库加载约束)控制可以加载到进程地址空间的代码。你还可以在 launchd plist 中为 Launch Agent/Daemon 指定约束。

Session 详述了各种使用场景:要求 app 只能从 Launch Services 作为应用程序启动、要求 XPC service 只能被特定 app 负责启动、要求 helper 只能被特定父进程启动等。这些约束通过字典形式的 plist 描述,支持嵌套的逻辑运算符。

值得深挖的点

Library Load Constraints 提供了比 Library Validation 更灵活的代码加载控制。Library Validation 只允许加载你签名或 Apple 签名的代码。Library Load Constraints 允许你描述一个更宽松但仍然安全的要求集。不过你不能排除 Apple 签名的代码,且必须指定至少一个允许你自己代码的属性。

macOS 在系统层面已经在使用环境约束来保护 OS 进程:要求从 Signed System Volume 运行、要求系统 daemon 只能从受保护的 launchd.plist 启动、要求系统 app 只能从 Launch Services 启动等。

代码片段

<!-- 启动约束示例 -->
<!-- 要求 app 只能作为应用程序从 Launch Services 启动 -->
<key>LaunchConstraints</key>
<dict>
    <key>Self</key>
    <dict>
        <key>LaunchType</key>
        <array>
            <string>Application</string>
        </array>
    </dict>
</dict>

<!-- XPC Service: 要求只被特定 app 负责 -->
<key>ResponsibleProcess</key>
<dict>
    <key>TeamIdentifier</key>
    <string>YOUR_TEAM_ID</string>
    <key>Identifier</key>
    <string>com.your.app</string>
</dict>

<!-- Library Load Constraint: 允许特定团队的代码 -->
<key>LibraryConstraints</key>
<dict>
    <key>TeamIdentifier</key>
    <array>
        <string>YOUR_TEAM_ID</string>
    </array>
</dict>

最佳实践

  • 环境约束是完全可选的,但能减少任何 app 的攻击面
  • 对于有多个进程或加载不同团队签名代码的 app 尤其有用
  • 为每个 helper/XPC service 设置合适的父进程和负责进程约束
  • 使用 Library Load Constraints 替代 Library Validation 获得更灵活的控制
  • 通过 SMAppService API 注册带有约束的 launchd plist

还有什么值得关注

  • macOS Ventura 已开始用环境约束保护系统进程
  • Sonoma 将使用范围扩展到了第三方 app
  • 配合 App Sandbox 和 Hardened Runtime 使用效果更佳
  • 约束以 plist 字典形式描述,支持 AND/OR/NOT 逻辑运算
WWDC 2023