hacktricks/mobile-pentesting/ios-pentesting/ios-basics.md

18 KiB
Raw Blame History

<details>

<summary><strong>从零到英雄学习AWS黑客攻击通过</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong></strong></summary>

支持HackTricks的其他方式

* 如果您想在**HackTricks中看到您的公司广告**或**下载HackTricks的PDF**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)
* 获取[**官方PEASS & HackTricks商品**](https://peass.creator-spring.com)
* 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs系列**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群组**](https://discord.gg/hRep4RUj7f)或[**telegram群组**](https://t.me/peass)或在**Twitter**上**关注**我 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**。**
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>


# 权限分离和沙盒

用户可以访问的应用程序作为**mobile**用户运行,而关键的系统进程则作为**root**运行。\
然而,沙盒允许更好地控制进程和应用程序可以执行的操作。

例如即使两个进程作为同一用户mobile运行它们也**不允许访问或修改彼此的数据**。

每个应用程序都安装在**`private/var/mobile/Applications/{随机ID}`**下\
一旦安装,应用程序对一些系统区域和功能(短信,电话呼叫...)有限的读取权限。如果应用程序想要访问**受保护的区域**,会出现**弹出请求权限**的弹窗。

# 数据保护

应用程序开发者可以利用iOS _数据保护_ API来实现对存储在闪存中的用户数据的**细粒度访问控制**。这些API建立在**安全加密处理器**SEP之上。SEP是一个协处理器为数据保护和密钥管理提供**加密操作**。一个设备特定的硬件密钥——**设备UID**唯一ID——**嵌入在安全加密区**,即使操作系统内核受到破坏,也能确保数据保护的完整性。

当在磁盘上**创建文件**时,会在安全加密区的硬件基础随机数生成器的帮助下生成一个新的**256位AES密钥**。然后,**文件的内容用生成的密钥加密**。接着,这个**密钥用一个类密钥加密并保存**,连同**类ID**,与**系统密钥加密的两个数据**一起,存储在文件的**元数据**中。

![](<../../.gitbook/assets/image (473).png>)

为了解密文件,**元数据使用系统密钥解密**。然后**使用类ID**来**检索类密钥****解密每个文件的密钥并解密文件**。

文件可以被分配到**四个**不同的**保护**类别中,这些类别在[苹果平台安全指南](https://help.apple.com/pdf/security/en_US/apple-platform-security-guide.pdf)中有更详细的解释:

* **完全保护NSFileProtectionComplete**这个类别的密钥由用户密码和设备UID派生的密钥保护。派生的密钥在设备锁定后不久就会从内存中擦除使得数据在用户解锁设备之前无法访问。
* **除非打开否则受保护NSFileProtectionCompleteUnlessOpen**:这个保护类别类似于完全保护,但是,如果文件在解锁时打开,即使用户锁定设备,应用程序也可以继续访问文件。例如,在后台下载邮件附件时会使用这个保护类别。
* **直到首次用户认证之前受保护NSFileProtectionCompleteUntilFirstUserAuthentication**:用户首次解锁设备后,文件就可以被访问。即使用户随后锁定了设备,类密钥也不会从内存中移除,文件仍然可以被访问。
* **无保护NSFileProtectionNone**这个保护类别的密钥仅由UID保护。类密钥存储在“可擦除存储”中这是iOS设备上的闪存区域允许存储少量数据。这个保护类别存在是为了快速远程擦除立即删除类密钥使数据无法访问。

除了`NSFileProtectionNone`之外的所有类密钥都用设备UID和用户密码派生的密钥加密。因此解密只能在设备本身上进行并且需要正确的密码。

自iOS 7以来默认的数据保护类别是“直到首次用户认证之前受保护”。

[**FileDP**](https://github.com/abjurato/FileDp-Source)是一个程序您可以上传并在iPhone内部使用它来**检查每个文件的数据保护类别**。

## 钥匙串

钥匙串是一个**加密的**容器,每个应用程序都可以在其中**存储**敏感信息,并且只有同一个应用程序(或授权的应用程序)可以检索内容。\
iOS**为钥匙串生成了自己的密码**并在设备上**存储**了这个密钥的**加密**版本。这个密码是用AES加密的AES密钥是由用户密码+盐256位设备**UID****仅**对设备上的安全**加密芯片组**可访问)的**PBKDF2**函数创建的。由于使用了这个设备UID作为盐即使知道用户密码一个设备也无法解密另一个设备的钥匙串。

钥匙串的访问由**`securityd`**守护进程管理,它根据应用程序的`Keychain-access-groups`、`application-identifier`和`application-group`权限来授予访问权限。

[钥匙串API](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/02concepts/concepts.html)包括以下主要操作:

* `SecItemAdd`
* `SecItemUpdate`
* `SecItemCopyMatching`
* `SecItemDelete`

尝试破解这个密码的唯一方法是转储加密的密钥并破解密码+盐(**pbkdf2**函数使用**至少10000次迭代**)。或者尝试**在设备内部破解**以避免破解盐,然而,安全加密区确保在两次失败的密码尝试之间至少有**5秒的延迟**。

您可以通过在调用`SecItemAdd`或`SecItemUpdate`时设置`kSecAttrAccessible`键来配置**钥匙串项目的数据保护**。以下是可配置的[钥匙串数据保护类别的可访问性值](https://developer.apple.com/documentation/security/keychain\_services/keychain\_items/item\_attribute\_keys\_and\_values#1679100)

* **`kSecAttrAccessibleAlways`**:无论设备是否锁定,钥匙串项目中的数据都可以**始终被访问**。
* **`kSecAttrAccessibleAlwaysThisDeviceOnly`**:无论设备是否锁定,钥匙串项目中的数据都可以**始终被访问**。数据**不会包含在iCloud**或本地备份中。
* **`kSecAttrAccessibleAfterFirstUnlock`**:重启后,在**用户首次解锁设备之前**,无法访问钥匙串项目中的数据。
* **`kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly`**:重启后,在**用户首次解锁设备之前**,无法访问钥匙串项目中的数据。具有此属性的项目**不会迁移到新设备**。因此,在从不同设备的备份恢复后,这些项目将不会出现。
* **`kSecAttrAccessibleWhenUnlocked`**:只有在用户**解锁设备时**,才能访问钥匙串项目中的数据。
* **`kSecAttrAccessibleWhenUnlockedThisDeviceOnly`**:只有在用户**解锁设备时**,才能访问钥匙串项目中的数据。数据**不会包含在iCloud或本地备份中**。
* **`kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly`**:只有在设备**解锁时**,才能访问钥匙串中的数据。这个保护类别**只有在设备上设置了密码时才可用**。数据**不会包含在iCloud或本地备份中**。

**`AccessControlFlags`**定义了用户可以通过哪些机制认证密钥(`SecAccessControlCreateFlags`

* **`kSecAccessControlDevicePasscode`**:通过密码访问项目。
* **`kSecAccessControlBiometryAny`**通过注册到Touch ID的一个指纹访问项目。添加或移除指纹不会使项目失效。
* **`kSecAccessControlBiometryCurrentSet`**通过注册到Touch ID的一个指纹访问项目。添加或移除指纹_会_使项目失效。
* **`kSecAccessControlUserPresence`**通过注册的指纹之一使用Touch ID或默认密码访问项目。

请注意通过Touch ID通过`kSecAccessControlBiometryAny`或`kSecAccessControlBiometryCurrentSet`)保护的密钥受到安全加密区的保护:钥匙串只持有一个令牌,而不是实际的密钥。密钥驻留在安全加密区中。

iPhone使用用户解锁设备时输入的密码来解密钥匙串中的秘密。

iOS使用_**AppIdentifierPrefix**_团队ID和_**BundleIdentifier**_由开发者提供来执行**对钥匙串项目的访问控制**。然后,同一个团队**可以**配置**2个应用程序共享钥匙串项目**。

当启动备份过程时,钥匙串中**备份的数据保持加密状态,钥匙串密码不包含在备份中**。

{% hint style="warning" %}
**在越狱设备上,钥匙串不受保护。**
{% endhint %}

### **钥匙串数据持久性**

在iOS上当应用程序被卸载时应用程序使用的钥匙串数据会被设备保留与应用程序沙盒存储的数据被擦除不同。如果**用户在没有执行出厂重置的情况下出售他们的设备,设备的买家可能能够通过重新安装前一个用户使用的相同应用程序来访问前一个用户的应用程序账户和数据**。这不需要任何技术能力来执行。

没有iOS API允许开发者在应用程序卸载时强制擦除数据。相反开发者应采取以下步骤来防止钥匙串数据在应用程序安装之间持久化

* 当应用程序在安装后首次启动时擦除与应用程序相关的所有钥匙串数据。这将防止设备的第二个用户意外获得前一个用户的账户。以下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
}
  • 在为iOS应用程序开发注销功能时请确保作为账户注销的一部分清除Keychain数据。这将允许用户在卸载应用程序之前清除他们的账户。

应用能力

每个应用都有一个独特的主目录并且被沙盒化因此它们不能访问受保护的系统资源或由系统或其他应用存储的文件。这些限制是通过沙盒策略又称为_profiles_实施的Trusted BSD (MAC) 强制访问控制框架通过内核扩展强制执行。

一些能力/权限可以由应用的开发者配置例如数据保护或Keychain共享并且在安装后将直接生效。然而对于其他的用户将在应用首次尝试访问受保护资源时被明确询问

用途字符串或_使用描述字符串_是在请求访问受保护数据或资源时在系统的权限请求警告中提供给用户的自定义文本。

如果拥有原始源代码,您可以在Info.plist文件中验证包含的权限:

  • 使用Xcode打开项目。
  • 在默认编辑器中找到并打开Info.plist文件,并搜索以"Privacy -"开头的键。

您可以通过右键点击并选择"显示原始键/值"来切换视图以显示原始值(这样例如"Privacy - Location When In Use Usage Description"将变为NSLocationWhenInUseUsageDescription)。

如果只有IPA

  • 解压IPA。
  • Info.plist位于Payload/<appname>.app/Info.plist
  • 如有需要,转换它(例如plutil -convert xml1 Info.plist),如"iOS基础安全测试"章节中的"The Info.plist File"部分所解释的。
  • 检查所有_用途字符串Info.plist键_通常以UsageDescription结尾:
<plist version="1.0">
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>您的位置用于提供前往目的地的逐步导航。</string>

设备能力

设备能力由App Store使用以确保只有兼容的设备被列出因此被允许下载应用。它们在应用的Info.plist文件中以UIRequiredDeviceCapabilities键指定。

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

通常你会发现 armv7 功能,意味着应用程序仅为 armv7 指令集编译,或者如果它是一个 32/64 位通用应用程序。

例如,一个应用程序可能完全依赖于 NFC 才能工作(例如,一个"NFC 标签阅读器"应用程序)。根据存档的 iOS 设备兼容性参考NFC 仅从 iPhone 7和 iOS 11开始可用。开发者可能希望通过设置 nfc 设备功能来排除所有不兼容的设备。

权限

权限是键值对,它们被签入应用程序,并允许超出运行时因素(如 UNIX 用户 ID的认证。由于权限是数字签名的它们无法被更改。权限被系统应用程序和守护进程广泛使用执行特定的特权操作,否则这些操作将要求进程以 root 身份运行。这大大减少了被损坏的系统应用程序或守护进程进行权限提升的潜力。

例如,如果你想设置“默认数据保护”功能,你需要转到 Xcode 中的 功能 标签并启用 数据保护。这直接由 Xcode 写入 <appname>.entitlements 文件作为 com.apple.developer.default-data-protection 权限,默认值为 NSFileProtectionComplete。在 IPA 中,我们可能会在 embedded.mobileprovision 中找到这一点:

<key>Entitlements</key>
<dict>
...
<key>com.apple.developer.default-data-protection</key>
<string>NSFileProtectionComplete</string>
</dict>

对于其他功能例如HealthKit必须请求用户的权限因此仅添加权限是不够的还必须在应用程序的Info.plist文件中添加特殊的键和字符串。

Objective-C 和 Swift 基础

Objective-C 有一个动态运行时所以当在iOS中执行Objective-C程序时它会调用库这些库的地址在运行时通过将消息中发送的函数名与所有可用函数名的列表进行比较来解析

起初只有苹果公司创建的应用程序才能在iPhone上运行所以它们可以访问一切,因为它们是可信的。然而,当苹果公司允许 第三方应用程序时,苹果公司只是移除了强大功能的头文件,以便向开发者“隐藏”它们。然而,开发者发现“安全”的功能需要一些这些未记录的功能,只需创建一个包含未记录功能名称的自定义头文件,就可以调用这些强大的隐藏功能。 实际上,在允许应用程序发布之前,苹果会检查应用程序是否调用了这些禁止的功能。

然后Swift出现了。由于Swift是静态绑定的它不像Objective-C那样在运行时解析函数的地址可以通过静态代码分析更容易地检查Swift程序将要进行的调用。

设备管理

从iOS版本6开始内置了对设备管理的支持具有细粒度控制允许组织控制企业苹果设备。
用户可以通过安装代理来启动注册,以便访问企业应用程序。在这种情况下,设备通常属于用户。
或者公司可以指定购买设备的序列号或采购订单ID并指定要在这些设备上安装的MDM配置文件。请注意苹果不允许以这种方式两次注册特定设备。一旦删除了第一个配置文件,用户需要同意安装另一个。

用户可以在 设置 --> 通用 --> 描述文件与设备管理 中查看已安装的策略

由于这些MDM策略正在检查和限制其他应用程序它们运行权限更高
MDM策略可以强制 用户设置具有最低密码复杂度密码
配置文件与设备ID绑定由MDM服务器签名加密,并且是防篡改的。它们不能移除,否则会丢失所有企业 数据
MDM配置文件允许在有X次失败的密码尝试擦除所有数据。此外,管理员可以通过MDM界面随时远程擦除iPhone。

MDM代理还将检查设备是否可能越狱因为这对iPhone来说是非常危险的状态。

通过 htARTE (HackTricks AWS Red Team Expert)从零到英雄学习AWS黑客攻击

支持HackTricks的其他方式