漏洞概述
就在前几天,Zero Day Initiative曾发布过六份关于苹果macOS中安全漏洞的公告,其中有一条公告涵盖了一个由 ABC Research s.r.o报告的安全漏洞,这个漏洞是苹果硬件GPU的设计缺陷,这也是他们所提交的众多macOS漏洞的其中一个。现在,这些漏洞已经在Big Sur中被修复了,因此在这篇文章中,我们将详细介绍关于漏洞ZDI-20-1403/CVE-2020-27897的细节信息,而这个漏洞将有可能允许攻击者实现提权并在内核上下文场景中执行任意代码。
某些型号的MacBook带有Intel图形模块,而macOS会使用内核扩展来管理它们,其中一个名为AppleIntelKBLGraphics,我们具体讨论的也是存在于该模块中的本地权限提升漏洞。
漏洞分析
用户空间和英特尔内核驱动程序之间的通信是使用IOConnectCallMethod完成的,而IOConnectCallMethod最终还会使用Mach消息。IntelMTRenderFunctions是一个类,它负责处理来自客户端的内核命令以便通过execute()方法来呈现UI信息。每个内核命令都由一个数值标识,在我们的例子中,我们将关注命令0x10005。除了内核命令号之外,execute()还可以接受来自客户端缓冲区的数据。此缓冲区中的偏移量用于生成结构地址的算术运算,这个运算操作会在未进行边界检查的情况下发生,并触发越界写入漏洞。
对于代码路径IntelMTLRenderFunctions::execute()的描述如下:用户空间客户端可以通过调用IOAccelSharedUserClient2::create_shmem()函数创建两个共享内存映射,该函数由另一个内核扩展IOAcceleratorFamily2提供。第一个内存映射将用作请求的分段描述符,而第二个内存映射包含一个命令缓冲区。create_shmem()函数将使用唯一的ID注册映射并返回它们,然后将这些ID与内核命令缓冲区一起传递给IOAccelCommandQueue::s_submit_command_buffers(),这个内核命令缓冲区的大致结构(数组)如下所示:
struct command { uint32_t type; uint32_t size; uint8_t *cmd; }
这个数组之后会进行分割,最终将以一个内核命令传递给IGAccelCommandQueue::processKernelCommand(),该内核命令结构如下:
struct command { uint32_t cmd_id; // 0x10005 uint32_t size; uint32_t offset; // the offset that causes no boundary check uint32_t loop_counter; uint32_t zero1; uint32_t zero2; uint32_t controlled_value; // controlled value which can be written to the offset uint32_t zero3; };
接下来,它将会传递给AppleIntelKBLGraphics中的IntelMTLRenderFunctions::execute()并处理内核命令0x10005:
下面给出的是针对该漏洞的利用PoC:
总结
内核驱动程序中的漏洞总是非常的有意思,它们的攻击向量往往需要伴随远程代码执行漏洞。一旦存在这种漏洞,那么将有可能导致目标设备完全被攻击者接管。