关于ZAKER 融媒体解决方案 智媒短视频 合作 加入

macOS 二进制 plist 解析的漏洞分析

属性表文件 ( Plist ) 是一种文件形式,通常用于储存用户设置,也可以用于存储捆绑的信息,该功能在旧式的 Mac OS 中是由资源分支提供的。由于 Plist 中存储的数据是抽象的,其采用的文件格式可以不止一种。

macOS 看起来非常有趣,尤其是属性列表 ( plists ) 是存储序列化对象的文件,在苹果操作系统中很常见,类似于微软 Windows 使用注册表存储配置数据。下面显示了 macOS 应用程序自动器的基于 xml 的属性列表示例。此属性列表存储应用程序的版本信息以及其他有用数据如下所示:

属性列表也可以采用二进制形式,否则称为 bplist。顾名思义,这些是二进制格式的属性列表,这些属性列表启用了一些附加的对象类型和关系,包括字典。以下是一个示例 bplist,尽管可以使用其他标签来支持该格式的其他版本,但是可以通过 bplist00 标记来标识该示例:

通过查看苹果的开源代码,可以更好地理解 bplist 格式,我也发现这个参考非常有用。苹果开源代码中定义的 bplist 格式如下:

二进制 plist 格式

属性列表为模糊测试提供了一个有趣的目标,因为它们很容易被操作系统的许多部分(包括更高特权的进程)创建和使用。苹果公司的开源代码使我能够创建任意的 bplist,并开始模糊文件格式,同时使用内置的 macOS plutil 命令行工具确保正确的语法。

我花了几天时间来生成 bplist 来执行该格式,并很快发现某些对象类型在被常见的 macOS 二进制文件(例如 Finder)以及更高特权的二进制文件(包括 Launch Services 守护程序(LSD))进行解析时会导致异常。系统崩溃日志表明 Core Foundation 框架中存在漏洞,但是,正如我们稍后将看到的,此漏洞存在于多个位置。Core Foundation(简称 CF)是一套 Mac OS 和 iOS 中的 C 语言 API,由较低层的一些例程和封装函数组成。Apple 发布的最大的一个 CF 开源项目叫 CFLite,基于 CFLite 可以开发跨 Mac OS X,Linux 和 Windows 平台的应用。另外一个第三方的开源实现叫做 OpenCFLite 也有同样的功能。大多数的 Core Foundation 例程的对象通常遵循这样的命名规则,例如:CFDictionary 开头的函数中会出现 CFDictionaryRef,这些对象经常被会手动通过 CFRetain 和 CFRelease 来管理引用计数。在内部,Core Foundation 也会把一些基础类型转成 Objective-C 运行时中可用的格式。

大多数生成的崩溃似乎是由 Core Foundation 解析 bplist 并随后尝试使用创建的对象的方式引起的。任何 bplist 的 ObjectTable 中有非字符串类型的对象 ( Date、Data、Bool 等 ) 都会在调用不存在的字符串相关选择器时导致解析过程崩溃。其结果是,任何使用 Core Foundation 读取属性列表的进程都可能因无法识别的选择器异常而崩溃。下面是一个示例易受攻击的代码路径:

使用以下 C 代码以及与测试应用程序位于同一目录中的名为 Info.plist 的恶意属性列表,可以轻松到达此位置:

崩溃分析

可以通过编程方式或通过将修改后的 bplist 放置在系统上自动对其进行分析的方式来为此漏洞生成崩溃,实际上,此漏洞的最初迹象之一是 LSD 在尝试使用修改后的属性列表注册应用程序时反复在我的系统上崩溃。

Objective-See 有一篇很棒的博客文章,详细介绍了通过 LSD 进行的应用程序注册以及属性列表的自动解析。

下图是控制台输出,显示了在我的桌面上以合法的 Info.plist 身份修改后的 bplist 导致崩溃发生的频率,还请注意用户级和系统级进程崩溃。

LSD 崩溃

通过修改单个字节以将 ASCII 字符串对象(类型 0x5X)更改为另一种对象类型,如 DATE(类型 0x33),可以创建恶意的 bplist。修改后的 bplist 示例如下:

这个很小的字节更改现在可以用于在 macOS 系统和 iOS 上造成严重破坏,尽管在此研究中未对该平台进行过测试。这种方法还会影响包括 Spotlight 在内的多个数据库,这些数据库已被该恶意 Info.plist 攻击,甚至在重新启动后也反复导致崩溃。

漏洞是如何发现的?

由于能够轻松地重新创建崩溃,因此我深入研究了该漏洞的实际发生位置。跟踪此漏洞的一种简单方法是查看崩溃进程的堆栈跟踪。以下是前面显示的测试应用程序的崩溃日志,该日志使用 Core Foundation 读取了恶意属性列表。

阅读这篇文章以了解 Core Foundation 如何处理无法识别的选择器异常并阐明堆栈跟踪中的 _CF_forwarding_prep_0 会很有帮助。有了这些信息,我将之前的返回地址视为 CFStringFind 中的异常的可能来源,尤其是在调用 _CFStringGetLength 之后。下面的反汇编说明了此调用:

CFString 查找反汇编

我逐步完成了 LLDB 中的 CFStringFind,直到调用 _CFStringGetLength 来检查寄存器之前。从苹果的 _CFStringGetLength 文档中,我们知道第一个参数应该是字符串,因此我们可以使用以下 LLDB 命令检查 RDI 寄存器。

可以看到,第一个参数的对象类型不是字符串,而是恶意 bplist 中的 _NSDate 对象。下面的 _CFStringGetLength 的反编译说明了可能会出错的地方:

_CFStringGetLength 反编译

我们可以看到,在该函数的第一个参数上调用了长度选择器,我们知道该函数对于 _NSDate 对象将失败,因为它没有此选择器,该理论也与崩溃日志相匹配。

如果我们继续执行这个函数,则会最终将在 Objective-C 异常处理的内部遇到一个异常,这表明我们已找到这些崩溃的根本原因。

其他选择器

继续生成带有非字符串对象的 bplists,并且能够从其他无法识别的选择器在 Core Foundation 中生成其他崩溃。下面的崩溃日志是 LSD 在使用了一个恶意 bplist 和一个剩余的 nscfdata 对象后的崩溃日志:

此 LSD 崩溃的堆栈跟踪如下:

注意,在 Objective-C 异常处理之前,崩溃的位置不是来自 CFStringFind,而是实际上调用 _CFStringGetCStringPtrInternal 的 CFStringFindWithOptionsAndLocale,最终由于调用错误的选择器 _fastCStringContents 而崩溃。这样做的原因是,剩余的 nscfdata 类型实际上有一个长度选择器,所以它成功地通过了我们之前看到的第一个崩溃位置,并进一步进入 Core Foundation,直到它调用另一个未识别的选择器。

多个漏洞的发现

在此研究的早期,我使用 plutil 从恶意 bplist 生成崩溃,然后编写了自己的代码以到达必要的代码路径。以下命令通过使用 plutil 作为目标进程和 print plist 标志来设置一个 LLDB 会话,以开始调试此崩溃,该标志只会打印出人类可读版本的属性列表。

经过几次执行之后,很明显 plutil 实际上在其他位置崩溃,而不是在 Core Foundation 中崩溃。下面的输出说明了它试图在 __NSDate 类型上调用长度选择器,该类型会导致无法识别的选择器异常,但是此漏洞存在于 plutil 中,而不存在于 Core Foundation 中。

似乎在许多 macOS 应用程序中存在类似的漏洞,这些漏洞假定 bplists 仅包含字符串对象类型。 LSD 进程崩溃的堆栈跟踪如下所示:

如果我们使用 GHIDRA 来反汇编 _LSPlistCompactString 函数,则可以看到偏移量 45 或 0x2D 导致我们又对漏洞对象类型进行了另一个长度调用,大概是从我们现在在 LSD 数据库中的恶意 bplist 调用的:

我们可以通过在 _LSPlistCompactString 上设置断点并使用以下断点命令打印第一个参数来验证这一点:

下面的输出说明 LSD 正在从恶意 bplist 获取 __NSDate 对象:

这证实了我最初认为的一个漏洞实际上是多个 macOS 二进制文件中的许多漏洞,并且所有漏洞均源于 bplist 仅包含字符串对象的假设。

恶意影响

1. 根级进程可能会在普通用户帐户中崩溃,并且如果操作系统重新生成了根级进程,则它们会反复崩溃(例如,LSD 和 MDS)。

2. 系统不稳定和拒绝服务特别是在 Finder 或其他与 UI 相关的进程消耗了恶意 bplist 并使崩溃进程需要崩溃 0-click 时发生,因为应用程序捆绑包,程序包等在写入磁盘时会自动进行处理。

3. 有可能使普通用户帐户中与安全相关的进程崩溃,从而删除安全边界(XProtect 等),尽管本文中并未对其进行全面探讨。

4. 在自动分析 bplist 的情况下有可能被远程利用。

5. 受此漏洞影响的系统组件包括使用 Core Foundation 解析 bplist 的应用程序,占很大的比例,在 macOS 10.15.3 上快速搜索了 1000 多个已安装的二进制文件,这些文件导入了实现此漏洞的函数。

6. 许多应用程序通过 Core Foundation 解析 bplist 数据,但也会在自己的代码中错误地访问生成的对象,这意味着漏洞发生的概率可能更大。

以上内容由"嘶吼RoarTalk"上传发布 查看原文

觉得文章不错,微信扫描分享好友

扫码分享

热门订阅 换一批

查看全部