跳过内容

iOS 平台概述

iOS 是一种移动操作系统,为包括 iPhone、iPad 和 iPod Touch 在内的 Apple 移动设备提供支持。它也是 Apple tvOS 的基础,tvOS 继承了 iOS 的许多功能。本节从架构的角度介绍 iOS 平台。将讨论以下五个关键领域

  1. iOS 安全架构
  2. iOS 应用程序结构
  3. 进程间通信 (IPC)
  4. iOS 应用程序发布
  5. iOS 应用程序攻击面

与 Apple 桌面操作系统 macOS(以前称为 OS X)一样,iOS 基于 Darwin,这是一种由 Apple 开发的开源 Unix 操作系统。Darwin 的内核是 XNU(“X is Not Unix”),这是一个混合内核,结合了 Mach 和 FreeBSD 内核的组件。

但是,iOS 应用的运行环境比桌面应用更加受限。iOS 应用在文件系统级别彼此隔离,并且在系统 API 访问方面受到显着限制。

为了保护用户免受恶意应用程序的侵害,Apple 限制并控制对允许在 iOS 设备上运行的应用程序的访问。Apple 的 App Store 是唯一的官方应用程序分发平台。开发人员可以在这里提供他们的应用程序,消费者可以购买、下载和安装应用程序。这种分发方式不同于 Android,Android 支持多个应用商店和侧载(无需使用官方 App Store 即可在 iOS 设备上安装应用)。在 iOS 中,侧载通常指的是通过 USB 安装应用程序的方法,尽管还有其他不使用 App Store 的企业 iOS 应用程序分发方法,该方法包含在Apple Developer Enterprise Program中。

过去,只有通过越狱或复杂的方法才能进行侧载。对于 iOS 9 或更高版本,可以通过 Xcode 进行侧载

iOS 应用程序通过 Apple 的 iOS 沙盒(历史上称为 Seatbelt)相互隔离,这是一种强制访问控制 (MAC) 机制,描述了应用程序可以访问和无法访问的资源。与 Android 广泛的 Binder IPC 工具相比,iOS 提供的 IPC(进程间通信)选项非常少,从而最大限度地减少了潜在的攻击面。

统一的硬件和紧密的硬件/软件集成创造了另一个安全优势。每个 iOS 设备都提供安全功能,例如安全启动、硬件支持的 Keychain 和文件系统加密(在 iOS 中称为数据保护)。iOS 更新通常会迅速推广给很大一部分用户,从而减少了对支持旧的、未受保护的 iOS 版本的需求。

尽管 iOS 具有众多优势,但 iOS 应用程序开发人员仍然需要担心安全性。数据保护、Keychain、Touch ID/Face ID 身份验证和网络安全仍然存在很大的错误空间。在以下章节中,我们将描述 iOS 安全架构,解释基本的安全测试方法,并提供逆向工程操作方法。

iOS 安全架构

iOS 安全架构,由 Apple 在 iOS 安全指南中正式记录,由六个核心功能组成。Apple 会为每个主要的 iOS 版本更新此安全指南

  • 硬件安全
  • 安全启动
  • 代码签名
  • 沙盒
  • 加密和数据保护
  • 通用漏洞缓解

硬件安全

iOS 安全架构很好地利用了基于硬件的安全功能,这些功能可以提高整体性能。每个 iOS 设备都带有两个内置的 Advanced Encryption Standard (AES) 256 位密钥。设备的唯一 ID (UID) 和设备组 ID (GID) 是在制造过程中熔断 (UID) 或编译 (GID) 到应用程序处理器 (AP) 和安全 enclave 处理器 (SEP) 中的 AES 256 位密钥。没有直接的方法可以通过软件或调试界面(例如 JTAG)读取这些密钥。加密和解密操作由具有对这些密钥的独占访问权限的硬件 AES 加密引擎执行。

GID 是设备类中所有处理器共享的值,用于防止篡改固件文件和其他与用户私有数据没有直接关系的加密任务。UID 是每个设备独有的,用于保护密钥层次结构,该层次结构用于设备级文件系统加密。由于 UID 未在制造过程中记录,因此即使是 Apple 也无法恢复特定设备的文件加密密钥。

为了允许安全删除闪存上的敏感数据,iOS 设备包含一项名为 Effaceable Storage 的功能。此功能提供对存储技术的直接低级访问,从而可以安全地擦除选定的块。

安全启动

当 iOS 设备开机时,它会从只读存储器(称为 Boot ROM)读取初始指令,该指令引导系统。Boot ROM 包含不可变代码和 Apple Root CA,它们在制造过程中蚀刻到硅芯片中,从而创建信任根。接下来,Boot ROM 确保 LLB(低级别引导加载程序)的签名正确,并且 LLB 检查 iBoot 引导加载程序的签名是否也正确。签名验证后,iBoot 检查下一个启动阶段的签名,即 iOS 内核。如果这些步骤中的任何一个失败,启动过程将立即终止,设备将进入恢复模式并显示恢复屏幕。但是,如果 Boot ROM 无法加载,设备将进入一种特殊的低级恢复模式,称为设备固件升级 (DFU)。这是将设备恢复到原始状态的最后手段。在这种模式下,设备将不显示任何活动迹象;即,其屏幕将不显示任何内容。

整个过程称为“安全启动链”。它的目的侧重于验证启动过程的完整性,确保系统及其组件是由 Apple 编写和分发的。安全启动链由内核、引导加载程序、内核扩展和基带固件组成。

代码签名

Apple 实施了一个精心设计的 DRM 系统,以确保只有 Apple 批准的代码才能在其设备上运行,即 Apple 签名的代码。换句话说,除非 Apple 明确允许,否则您将无法在未越狱的 iOS 设备上运行任何代码。最终用户应该只通过官方 Apple App Store 安装应用程序。出于这个原因(以及其他原因),iOS 被比作水晶监狱

部署和运行应用程序需要开发人员配置文件和 Apple 签名的证书。开发人员需要向 Apple 注册,加入Apple Developer Program并支付年度订阅费,才能获得全面的开发和部署可能性。还有一个免费的开发人员帐户,允许您编译和部署应用程序(但不能通过侧载将其分发到 App Store)。

根据存档的 Apple Developer 文档,代码签名由三部分组成

  • 印章。这是代码签名软件创建的各种代码部分的校验和或哈希值的集合。印章可在验证时用于检测更改。
  • 数字签名。代码签名软件使用签名者的身份加密印章以创建数字签名。这保证了印章的完整性。
  • 代码要求。这些是管理代码签名验证的规则。根据目标,有些规则是验证者固有的,而另一些规则是由签名者指定的并与代码的其余部分一起密封。

了解更多

加密和数据保护

FairPlay 代码加密应用于从 App Store 下载的应用程序。FairPlay 开发为购买多媒体内容时的 DRM。最初,FairPlay 加密应用于 MPEG 和 QuickTime 流,但相同的基本概念也可以应用于可执行文件。基本思想如下:一旦您注册新的 Apple 用户帐户或 Apple ID,系统将创建一对公钥/私钥并将其分配给您的帐户。私钥安全地存储在您的设备上。这意味着 FairPlay 加密的代码只能在与您的帐户关联的设备上解密。反向 FairPlay 加密通常是通过在设备上运行应用程序,然后从内存中转储解密的代码来获得的(另请参见“iOS 上的基本安全测试”)。

自 iPhone 3GS 发布以来,Apple 已将加密内置到其 iOS 设备的硬件和固件中。每个设备都有一个专用的基于硬件的加密引擎,该引擎提供了 AES 256 位加密和 SHA-1 哈希算法的实现。此外,每个设备的硬件中都内置了一个唯一的标识符 (UID),其中 AES 256 位密钥熔断到应用程序处理器中。此 UID 是唯一的,未在其他地方记录。在撰写本文时,软件和固件都无法直接读取 UID。由于密钥已烧录到硅芯片中,因此无法篡改或绕过它。只有加密引擎才能访问它。

将加密构建到物理架构中使其成为可以加密存储在 iOS 设备上的所有数据的默认安全功能。因此,数据保护在软件级别实现,并且与硬件和固件加密一起使用以提供更高的安全性。

启用数据保护后,只需在移动设备中建立密码,每个数据文件都与特定的保护类相关联。每个类都支持不同的可访问级别,并根据何时需要访问数据来保护数据。与每个类关联的加密和解密操作基于多种密钥机制,这些机制利用设备的 UID 和密码、类密钥、文件系统密钥和每个文件的密钥。每个文件的密钥用于加密文件的内容。类密钥包装在每个文件的密钥周围并存储在文件的元数据中。文件系统密钥用于加密元数据。UID 和密码保护类密钥。此操作对用户不可见。要启用数据保护,访问设备时必须使用密码。密码会解锁设备。与 UID 结合使用时,密码还会创建更耐黑客攻击和强力攻击的 iOS 加密密钥。启用数据保护是用户在其设备上使用密码的主要原因。

沙盒

应用程序沙盒是一种 iOS 访问控制技术。它在内核级别强制执行。它的目的是限制应用程序受到威胁时可能发生的系统和用户数据损坏。

自 iOS 的第一个版本以来,沙盒一直是核心安全功能。所有第三方应用程序都在同一用户 (mobile) 下运行,只有少数系统应用程序和服务以 root(或其他特定系统用户)身份运行。常规 iOS 应用程序被限制在一个容器中,该容器限制对应用程序自身文件和非常有限数量的系统 API 的访问。对所有资源(例如文件、网络套接字、IPC 和共享内存)的访问都由沙盒控制。这些限制的工作方式如下 [#levin]

  • 应用程序进程通过类似 chroot 的进程限制在其自己的目录中(在 /var/mobile/Containers/Bundle/Application/ 或 /var/containers/Bundle/Application/ 下,具体取决于 iOS 版本)。
  • mmapmmprotect 系统调用被修改,以防止应用程序使可写内存页面可执行,并阻止进程执行动态生成的代码。结合代码签名和 FairPlay,这严格限制了什么代码可以在特定情况下运行(例如,通过 App Store 分发的所有应用程序中的所有代码都经过 Apple 的批准)。
  • 即使进程由操作系统级别的同一 UID 拥有,它们也会彼此隔离。
  • 无法直接访问硬件驱动程序。相反,必须通过 Apple 的公共框架访问它们。

通用漏洞缓解

iOS 实现了地址空间布局随机化 (ASLR) 和 eXecute Never (XN) 位来缓解代码执行攻击。

ASLR 每次执行程序时都会随机化程序的可执行文件、数据、堆和堆栈的内存位置。由于共享库必须是静态的才能被多个进程访问,因此共享库的地址会在每次 OS 启动时而不是每次调用程序时随机化。这使得特定的函数和库内存地址难以预测,从而防止了诸如 return-to-libc 攻击之类的攻击,该攻击涉及基本 libc 函数的内存地址。

XN 机制允许 iOS 将进程的选定内存段标记为不可执行。在 iOS 上,用户模式进程的进程堆栈和堆被标记为不可执行。可写的页面不能同时标记为可执行。这可以防止攻击者执行注入到堆栈或堆中的机器代码。

iOS 上的软件开发

与其他平台一样,Apple 提供了一个软件开发工具包 (SDK),可以帮助开发人员开发、安装、运行和测试本机 iOS 应用程序。Xcode 是 Apple 软件开发的集成开发环境 (IDE)。iOS 应用程序使用 Objective-C 或 Swift 开发。

Objective-C 是一种面向对象的编程语言,它将 Smalltalk 样式的消息传递添加到 C 编程语言中。它在 macOS 上用于开发桌面应用程序,在 iOS 上用于开发移动应用程序。Swift 是 Objective-C 的后继者,允许与 Objective-C 互操作。

Swift 是在 2014 年通过 Xcode 6 引入的。

在非越狱设备上,有两种方法可以在 App Store 之外安装应用程序

  1. 通过企业移动设备管理。这需要一个由 Apple 签名的公司范围的证书。
  2. 通过侧载,即通过使用开发人员证书对应用程序进行签名并通过 Xcode(或 Cydia Impactor)将其安装到设备上。可以使用同一证书安装有限数量的设备。

iOS 上的应用

iOS 应用程序以 IPA(iOS App Store Package)存档形式分发。IPA 文件是一个 ZIP 压缩存档,其中包含执行应用程序所需的所有代码和资源。

IPA 文件具有内置的目录结构。下面的示例以高级别显示此结构

  • /Payload/ 文件夹包含所有应用程序数据。我们将在稍后更详细地讨论此文件夹的内容。
  • /Payload/Application.app 包含应用程序数据本身(ARM 编译的代码)和相关的静态资源。
  • /iTunesArtwork 是一个 512x512 像素的 PNG 图像,用作应用程序的图标。
  • /iTunesMetadata.plist 包含各种信息,包括开发人员的姓名和 ID、捆绑包标识符、版权信息、类型、应用程序名称、发布日期、购买日期等。
  • /WatchKitSupport/WK 是扩展捆绑包的示例。此特定捆绑包包含扩展委托和控制器,用于管理界面和响应 Apple Watch 上的用户交互。

IPA Payload - 深入了解

让我们更详细地了解 IPA 容器中的不同文件。Apple 使用相对扁平的结构,其中包含很少的无关目录,以节省磁盘空间并简化文件访问。顶级捆绑包目录包含应用程序的可执行文件和应用程序使用的所有资源(例如,应用程序图标、其他图像和本地化内容。

  • MyApp:包含编译后的(不可读)应用程序源代码的可执行文件。
  • Application:应用程序图标。
  • Info.plist:配置信息,例如捆绑包 ID、版本号和应用程序显示名称。
  • 启动图像:显示特定方向上的初始应用程序界面的图像。系统使用提供的启动图像之一作为临时背景,直到应用程序完全加载。
  • MainWindow.nib:启动应用程序时加载的默认界面对象。然后从其他 nib 文件加载其他界面对象,或由应用程序以编程方式创建。
  • Settings.bundle:要在“设置”应用程序中显示的特定于应用程序的首选项。
  • 自定义资源文件:非本地化资源放置在顶级目录中,本地化资源放置在应用程序捆绑包的特定于语言的子目录中。资源包括 nib 文件、图像、声音文件、配置文件、字符串文件以及应用程序使用的任何其他自定义数据文件。

每个应用程序支持的语言都有一个 language.lproj 文件夹。它包含一个情节提要和字符串文件。

  • 情节提要是一个 iOS 应用程序用户界面的可视化表示。它显示屏幕和这些屏幕之间的连接。
  • 字符串文件格式由一个或多个键值对和可选注释组成。

在越狱设备上,您可以使用不同的工具恢复已安装的 iOS 应用程序的 IPA,这些工具允许解密主应用程序二进制文件并重建 IPA 文件。同样,在越狱设备上,您可以使用 ipainstaller 安装 IPA 文件。在移动安全评估期间,开发人员通常会直接向您提供 IPA。他们可以将实际文件发送给您,或者提供对他们使用的特定于开发的发布平台的访问权限,例如 TestFlightVisual Studio App Center

应用权限

与 Android 应用程序(在 Android 6.0(API 级别 23)之前)相比,iOS 应用程序没有预先分配的权限。相反,当应用程序首次尝试使用敏感 API 时,系统会要求用户授予权限。已获得权限的应用程序会在“设置”>“隐私”菜单中列出,允许用户修改特定于应用程序的设置。Apple 将此权限概念称为隐私控制

iOS 开发人员无法直接设置请求的权限,这些权限会在访问敏感 API 时间接请求。例如,当访问用户的联系人时,对 CNContactStore 的任何调用都会阻止应用程序,同时要求用户授予或拒绝访问权限。从 iOS 10.0 开始,应用程序必须包含它们请求的权限类型和需要访问的数据的使用描述键(例如,NSContactsUsageDescription)。

以下 API 需要用户权限

  • 联系人
  • 麦克风
  • 日历
  • 相机
  • 提醒事项
  • HomeKit
  • 照片
  • 健康
  • 运动活动和健身
  • 语音识别
  • 定位服务
  • 蓝牙共享
  • 媒体库
  • 社交媒体帐户

DeviceCheck

DeviceCheck 框架(包括其组件 DeviceCheck 和 App Attest)可帮助您防止欺诈性地使用您的服务。它由一个框架组成,您从您的应用程序中使用该框架,以及一个只能由您自己的服务器访问的 Apple 服务器。DeviceCheck 允许您在设备和 Apple 服务器上持久存储信息。存储的信息在应用程序重新安装、设备传输或重置后仍然完好无损,可以选择定期重置此数据。

DeviceCheck 通常用于通过限制对敏感资源的访问来减轻欺诈。例如,将促销活动限制为每台设备一次,识别并标记欺诈设备等。但是,它绝对不能防止所有欺诈行为。例如,它并非旨在检测受损的操作系统(又名越狱检测)。

有关更多信息,请参阅DeviceCheck 文档

App Attest

App Attest 在 DeviceCheck 框架下可用,它通过使应用程序能够将硬件支持的断言附加到请求,确保它们来自真实 Apple 设备上的合法应用程序,从而帮助您验证设备上运行的应用程序实例。此功能有助于防止修改后的应用程序与您的服务器通信。

该过程涉及生成和验证加密密钥,以及您的服务器执行的一组验证,以确保请求的真实性。重要的是要注意,虽然 App Attest 可以增强安全性,但它不能保证完全防止所有形式的欺诈活动。

有关更多详细信息,请参阅 WWDC 2021 会议,以及“DeviceCheck 文档”“验证连接到您服务器的应用程序”