iOS Basics

支持 HackTricks

权限分离与沙箱

在 iOS 中,用户可访问的应用程序与系统核心进程之间存在权限区分。应用程序在 mobile 用户身份下运行,而关键的系统进程则以 root 身份运行。这种分离通过沙箱机制得到了增强,该机制对应用程序可以执行的操作施加了严格限制。例如,即使应用程序共享相同的用户身份,它们也被禁止访问或修改彼此的数据。

应用程序安装在特定目录(private/var/mobile/Applications/{random ID})中,并对某些系统区域和功能(如短信和电话)具有有限的读取访问权限。访问受保护区域会触发用户权限请求的弹出窗口。

数据保护

iOS 为开发者提供了 数据保护 API,该 API 建立在安全隔离处理器(SEP)之上——一个专门用于加密操作和密钥管理的协处理器。SEP 通过嵌入其中的唯一设备特定密钥(设备 UID)确保数据保护的完整性。

在文件创建时,会生成一个唯一的 256 位 AES 加密密钥,用于加密文件内容。该加密密钥与类 ID 一起,使用类密钥进行加密并存储在文件的元数据中。解密文件涉及使用系统密钥访问元数据,使用类 ID 检索类密钥,然后解密文件的唯一加密密钥。

iOS 定义了 四个保护类 用于数据安全,决定何时以及如何访问数据:

  • 完全保护 (NSFileProtectionComplete):在使用用户密码解锁设备之前,数据无法访问。

  • 除非打开受保护 (NSFileProtectionCompleteUnlessOpen):即使设备被锁定,只要在设备解锁时打开了文件,仍然允许访问文件。

  • 直到第一次用户身份验证受保护 (NSFileProtectionCompleteUntilFirstUserAuthentication):在首次用户解锁后,数据可访问,即使设备再次被锁定也保持可访问。

  • 无保护 (NSFileProtectionNone):数据仅由设备 UID 保护,便于快速远程数据擦除。

所有类的加密,除了 NSFileProtectionNone,都涉及一个由设备 UID 和用户密码派生的密钥,确保只有在具有正确密码的设备上才能解密。从 iOS 7 开始,默认保护类为“直到第一次用户身份验证受保护”。

开发者可以使用 FileDP 工具检查 iPhone 上文件的数据保护类。

# Example code to use FileDP for checking file protection class
# Note: Ensure your device is jailbroken and has Python installed to use FileDP.
# Installation and usage of FileDP:
git clone https://github.com/abjurato/FileDp-Source
cd FileDp-Source
python filedp.py /path/to/check

钥匙串

在 iOS 中,钥匙串作为一个安全的加密容器,用于存储敏感信息,仅可由存储它的应用程序或那些明确授权的应用程序访问。这种加密由 iOS 生成的唯一密码增强,该密码本身使用AES加密。此加密过程利用PBKDF2 函数,将用户的密码与来自设备的UID派生的盐结合,只有安全隔离芯片可以访问该组件。因此,即使用户的密码已知,钥匙串的内容在任何其他设备上仍然无法访问,只有在最初加密的设备上才能访问。

钥匙串数据的管理和访问由**securityd 守护进程**处理,基于特定的应用程序权限,如 Keychain-access-groupsapplication-identifier

钥匙串 API 操作

钥匙串 API 的详细信息请参见 Apple 的钥匙串服务文档,提供了安全存储管理的基本功能:

  • SecItemAdd:向钥匙串添加新项目。

  • SecItemUpdate:更新钥匙串中的现有项目。

  • SecItemCopyMatching:从钥匙串中检索项目。

  • SecItemDelete:从钥匙串中删除项目。

暴力破解钥匙串密码涉及直接攻击加密密钥或尝试在设备上猜测密码,这在很大程度上受到安全隔离的强制延迟的阻碍。

配置钥匙串项目数据保护

钥匙串项目的数据保护级别在项目创建或更新时使用 kSecAttrAccessible 属性设置。这些级别,如 Apple 所指定,决定了钥匙串项目何时以及如何可访问:

  • kSecAttrAccessibleAlways:随时可访问,无论设备锁定状态如何。

  • kSecAttrAccessibleAlwaysThisDeviceOnly:始终可访问,但不包括在备份中。

  • kSecAttrAccessibleAfterFirstUnlock:在重启后的第一次解锁后可访问。

  • kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly:与上述相同,但不可转移到新设备。

  • kSecAttrAccessibleWhenUnlocked:仅在设备解锁时可访问。

  • kSecAttrAccessibleWhenUnlockedThisDeviceOnly:解锁时可访问,不包括在备份中。

  • kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly:需要设备密码,不包括在备份中。

AccessControlFlags 进一步细化访问方法,允许使用生物识别认证或密码。

越狱设备警告

越狱设备上,钥匙串的保护被破坏,构成重大安全风险。

钥匙串数据的持久性

与在应用程序卸载时删除的应用程序特定数据不同,钥匙串数据在设备上持久存在。这一特性可能使二手设备的新拥有者通过重新安装应用程序访问前一个拥有者的应用程序数据。建议开发者在应用程序安装或注销时主动清除钥匙串数据,以降低此风险。以下是一个 Swift 代码示例,演示如何在首次启动应用程序时清除钥匙串数据:

let userDefaults = UserDefaults.standard

if userDefaults.bool(forKey: "hasRunBefore") == false {
// Remove Keychain items here

// Update the flag indicator
userDefaults.set(true, forKey: "hasRunBefore")
userDefaults.synchronize() // Forces the app to update UserDefaults
}

应用程序能力

在应用程序开发领域,沙盒在增强安全性方面发挥着至关重要的作用。此过程确保每个应用程序在其独特的主目录中运行,从而防止其访问系统文件或其他应用程序的数据。这些限制的执行是通过沙盒策略进行的,这些策略是受信任的 BSD (MAC) 强制访问控制框架的一部分。

开发人员可以为他们的应用程序配置某些能力或权限,例如数据保护钥匙串共享。这些权限在应用程序安装后立即生效。然而,要访问某些受保护的资源,应用程序必须在第一次尝试时获得用户的明确同意。这是通过使用_目的字符串_或_使用描述字符串_来实现的,这些字符串在权限请求警报中呈现给用户。

对于有源代码访问权限的人,可以通过以下方式验证Info.plist文件中包含的权限:

  1. 在 Xcode 中打开项目。

  2. 找到并打开Info.plist文件。

  3. 搜索以“Privacy -”为前缀的键,并可以查看原始键/值以便于理解。

处理 IPA 文件时,可以按照以下步骤进行:

  1. 解压 IPA。

  2. Payload/<appname>.app/中找到Info.plist文件。

  3. 如有必要,将文件转换为 XML 格式,以便于检查。

例如,Info.plist文件中的目的字符串可能如下所示:

<plist version="1.0">
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your location is used to provide turn-by-turn directions to your destination.</string>

Device Capabilities

应用程序的 Info.plist 文件指定了 设备能力,帮助 App Store 过滤与设备兼容的应用程序。这些在 UIRequiredDeviceCapabilities 键下定义。例如:

<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>

这个例子表明该应用程序与 armv7 指令集兼容。开发人员还可以指定诸如 nfc 的功能,以确保他们的应用程序仅在支持 NFC 的设备上可用。

权限

权限是 iOS 应用开发的另一个关键方面,作为键值对,授予应用程序执行某些操作的权限,超出运行时检查。例如,在应用程序中启用 数据保护 涉及在 Xcode 项目中添加特定权限,这随后反映在应用程序的权限文件或 IPA 的嵌入式移动配置文件中。

参考文献

支持 HackTricks

Last updated