freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

苹果OTA更新的噩梦:绕过签名验证和内核任意代码执行
2023-11-07 11:27:36

写在前面的话

本文由研究人员Mickey发表于其个人博客,内容来源于该研究人员在OBTS v6.0上的演讲内容,本文将讨论苹果的OTA更新机制细节,更新过程中暴露的安全问题,以及绕过SIP后如何实现任意内核代码执行。

苹果的OTA更新

在大多数情况下,macOS更新是通过OTA更新过程完成的。OTA,即over-the-air。在系统设置中,我们可以通过点击“现在更新”按钮直接更新系统:

OTA更新机制属于增量更新,因此比完整的系统更新要更快,更新包体积也更小。

该机制主要用于次要版本更新,通常每两个月更新一次。但如果苹果认为内核中存在一个紧急高危漏洞,同时该漏洞已经被积极利用,且无法通过RSR(快速安全响应)进行修补的话,则会发布紧急OTA更新(从Apple CDN服务器下载):

从上表中可以看到,OTA软件包是为当前操作系统版本定制的。

比如说,为了更新到12.6,12.5和12.4的包是不同的。更新过程的本质是应用修补程序代码,因此不同的操作系统版本具有不同的修补程序代码。在大多数情况下,系统越旧,包大小越大。

OTA更新包内容

下载并解压缩OTA包后,可以看到包的内容如下:

boot目录中包含与引导过程相关的内容,增量更新的真正修补程序代码位于名为payloadv2的目录中。其中有一个名为payload.bom的关键文件,其中包含了OTA包中的所有条目及其校验和值,文件payload.bom.signature用于验证payload.bom文件的完整性,文件pre.bom和post.bom列出了更新前后系统上的所有条目及其校验和值,Info.plist文件提供了关于当前OTA包的一些基本信息,如预版本、目标版本等。

在payloadv2文件夹中,有一些重要的文件需要注意。新系统中的新数据文件会被压缩到名为data_payload的文件中,ecc_data文件夹包含一些与文件权限相关的文件,links.txt文件列出了新系统的所有硬链接,而removed.txt文件列出了需要从当前系统中删除的所有条目。

更新步骤

常规的OTA更新步骤可以抽象成下列三个阶段:

阶段1

系统下载UpdateBrainService的URL位于下面这个XML文件中:

System/Library/AssetsV2/com_apple_MobileAsset_MobileSoftwareUpdate_MacUpdateBrain/com_apple_MobileAsset_MobileSoftwareUpdate_MacUpdateBrain.xml:

我们可以看到相关的基地址URL和构建完整URL的路径参数,其中包含了版本信息、发布日期、包大小、SHA1值和其他有用的信息。

阶段1运行流程如下:

获取到下载URL之后,进程nsurlsessiond负责将UpdateBrainService下载到临时目录。同时,com.apple.StreamingUnzipService会将其解压缩到相同的临时位置。接下来,mobileassetd进程则将解压缩的内容移动到下列受信任位置:

/System/Library/AssetsV2/com_apple_MobileAsset_MobileSoftwareUpdate_MacUpdateBrain/

最后,在launchd进程生成UpdateBrainService之前,会将xpc服务Bundle复制到目标路径。

阶段2

阶段2和阶段1有些类似:

不同的是XML路径:

/System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/com_apple_MobileAsset_MacSoftwareUpdate.xml

以及下载URL和目标路径:

/System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/

阶段3

阶段3则是UpdateBrainService本身,特定的xpc服务信息如下:

绕过签名认证(CVE-2022-42791)

修改OTA包

根据之前的描述,我们可以确认的是OTA包的最终路径(/System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/)受SIP保护。

但提取的内容首先会存储在临时路径下:

/var/folders/zz/zyxvpxvq6csfxvn_n00000y800007k/T/com.apple.nsurlsessiond/CFNetworkDownload_XXXXXX.tmp/[hash].asset

而这个路径是完全没有限制的,它属于nsurlsessiond,且可以由root用户直接修改。

因此,在mobilesetd进程将其移动到受信任位置之前,我们有一个时间窗口来修改内容。这样一来,可信位置中OTA包的内容就不可信了,需要进行验证。

当我尝试直接替换payload.com文件时,由于权限问题,mobileassetd进程无法调用文件API,因此会拒绝移动到最终路径:

但事实是,一旦它通过了这里的检查,它将调用rename API并移动包的内容,所以我们替换目标文件为时还过早。

操作成功之后的日志如下:

幸运的是,字符串“Moving file in …”暗示着绕过检测的时间窗口期,因此一旦我们从日志中监控到了这个字符串,我们就可以替换目标文件了。

OTA包验证

正如之前所说,payload.bom文件会列出OTA包中所有的条目和其校验和:

下面的函数可以用于验证包内容

它会打开并读取payload.bom文件,并使用最终路径的真实摘要值来根payload.bom文件中指定的文件摘要值进行对比:

如果匹配不成功,函数返回false,验证失败。但如果它只验证payload.bom本身呢?

这里还有另一个函数负责执行验证,即verify_package_signature:

它首先会打开payload.bom文件并计算其SHA1,然后再打开payload.bom.signature文件并读取文件内容签名。接下来,它会从系统证书文件“/System/Library/SoftwareUpdateCertificates/iPhoneSoftwareUpdate.pem”中获取公钥,而这个公钥是受到SIP和SSV保护的:

最后,它会调用SecKeyVerifySignature API并使用公钥验证签名,计算SHA1和文件内容签名:

SIP绕过

能够绕过签名认证之后,我们就能够绕过SIP了。函数ParallelPatchRemoveFiles能够读取OTA包中的removed.txt文件,并删除txt文件中所有的条目:

此时,我们就能够通过修改txt文件来拿到一个用于移除任意SIP保护路径的原语。此方法适用于所有的macOS平台,包括Intel和苹果M芯片在内。

内核影响

如果想要在绕过SIP之后实现操作系统内核劫持,最大的问题就是SSV保护。SSV,即“Signed System Volume”,这个功能是macOS Big Sur才引入的新功能,但这个功能仍然使用了一个独立的只读系统卷宗来保护系统文件。

现在的事实在于,苹果需要通过OTA更新来升级操作系统内核文件,因此OTA更新过程必须能够具备“打破”SSV保护的能力。

那OTA更新又是如何做到的呢?

macOS系统有一个隐藏的更新卷宗(/System/Volumes/Update/mnt1),它是当前操作系统的快照,所有的补丁修复其实都应用到了这个快照上。如果更新成功,则更新并重启真实系统。如果更新失败,则回退到之前的快照。

在对UpdateBrainService进行深入分析之后,我们总结出了以下OTA更新流程:

Function Name

Action

verify_package_[signature|contents]

验证OTA包完整性

prepare_snapshot

/System/Volumes/Update/mnt1卷宗准备一个当前操作系统快照/snapshot

copy_patched_files

payloadv2/patches/XXX(BXDIFF5格式)补丁应用到快照上

copy_archived_files

payload.[000-999](AppleArchive格式)提取Payload并应用到快照上,根据payload.XXX.ecc(AppleArchive格式)文件修复文件权限

copy_archived_data_files

data_payload提取至快照

verify_postbom

根据post.bom验证快照中新系统文件的校验和

SIP绕过问题(CVE-2022-46722)

如下图所示:

提取的文件夹本身是受限的,但其中的文件和其他目录并不是受限的,比如说AssetData文件夹。因此,我们就可以直接修改OTA包的内容了。

这样一来,验证OTA包的完整性就完全没有了意义,我们可以在这个OTA包验证完成之后,修改OTA包内容,并直接拿到SIP绕过原语。

如何在绕过SIP之后实现内核渗透

我们可以直接通过SIP绕过原语来实现内核补丁文件替换,并最终执行任意内核代码。

通过监控“/System/Volumes/Update/restore.log”,我们发现它会在更新过程中输出一些有价值的信息,比如说“Unarchiving files in parallel…”:

这里我写了一个名为spin_for_log的函数并在所有的更新完成之后等待一个正确的时机:

这样一来,我们就可以尝试使用定制内容来替换原内核了。

降级风险(CVE-2023-35983)

UpdateBrainService的主执行文件其实是一个空调用:

所有的函数都是在UpdateBrainLibrary.dylib中实现的,更新代码也不例外:

因此,攻击者就可以通过替换dylib中的旧版本信息来实现降级攻击了,而且旧版本内容由苹果签名,Library验证也能通过。

跟OTA更新包类似,UpdateBrainService Bundle包可以被root用户修改,这样一来攻击者就能够在UpdateBrainService被移动到受信任路径之前替换其内容(旧版本内容),并实现降级。

苹果的解决方案

现在,苹果重新调整了整个流程,现在系统会确保整个进程是受信任的,且包内容不会被篡改。苹果具体的修复方案如下:

首先,nsurlsessiond进程会创建一个名为downloadDir的受限目录,然后将UpdateBrainService Bundle包下载到这个受信位置。接下来,新引入的com.apple.StreamingUnzipService.privileged.xpc服务会在受信位置同步进行解压缩操作。

当下载和解压操作完成之后,进程之后要执行的任务就和之前类似了。

需要注意的是,nsurlsessiond进程和com.apple.StreamingUnzipService.privileged.xpc服务现在拥有了新的特殊权限com.apple.rootless.storage.MobileAssetDownload来修改受限目录。

值得一提的是,OTA包的下载过程现在也遵循这种新的处理流程了。

PoC概念验证

PoC地址:【CVE-2022-46722

安全演示

演示视频:【点我观看

参考文献

https://jhftss.github.io/The-Nightmare-of-Apple-OTA-Update/

# 更新 # OTA # 安全更新 # 苹果安全
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录