Pwn2Own Safari沙箱逃逸第一部分:获取root shell的技术分析

本文详细分析了CVE-2017-2533漏洞,该漏洞存在于macOS的Disk Arbitration守护进程中,通过竞争条件可实现从本地管理员到root的权限提升,并最终用于Safari沙箱逃逸。

Pwn2Own: Safari沙箱逃逸第一部分 - 获取root shell

今天我们将介绍CVE-2017-2533/ZDI-17-357漏洞,这是macOS系统服务中的一个竞争条件漏洞,可用于从本地管理员权限提升至root权限。我们在今年的Pwn2Own比赛中结合其他逻辑漏洞利用它来逃逸Safari沙箱。

该漏洞存在于Disk Arbitration守护进程(diskarbitrationd)中,该进程负责管理macOS上的块设备。其IPC接口可以从Safari沙箱内部访问,这使其成为我们感兴趣的目标。通过利用此漏洞,我们可以将磁盘分区挂载到任何不受SIP保护的目录上。由于每台新款MacBook都有一个允许默认用户写入的小型FAT32恢复分区,这使我们能够将任意内容的文件放入文件系统并获得root权限。

漏洞发现

在Safari渲染器中实现代码执行后,我们的目标是横向移动到更高权限的系统进程,因此我们通过查看允许的mach查找列表(即可以通过mach IPC通信的服务)开始审计。该列表可以在沙箱规则文件/System/Library/Frameworks/WebKit.framework/Versions/A/Resources/com.apple.WebProcess.sb中找到。

列表中的第一个服务com.apple.DiskArbitration.diskarbitrationd立即引起了我们的注意。Disk Arbitration是Apple负责管理(主要是挂载和卸载)块设备的框架,diskarbitrationd是处理相应IPC请求的服务。为什么浏览器渲染器需要挂载磁盘?这绝对值得进一步调查。

漏洞分析

我们发现漏洞存在于DARequest.c文件的以下代码中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
if ( DADiskGetDescription( disk, kDADiskDescriptionVolumePathKey ) == NULL )
{
    if ( DARequestGetUserUID( request ) )
    {
        CFTypeRef mountpoint;
        mountpoint = DARequestGetArgument2( request );
        // [...]
        if ( mountpoint )
        {
            char * path;
            path = ___CFURLCopyFileSystemRepresentation( mountpoint );
            if ( path )
            {
                struct stat st;
                if ( stat( path, &st ) == 0 )
                {
                    if ( st.st_uid != DARequestGetUserUID( request ) )
                    {
                        status = kDAReturnNotPermitted;
                    }
                }

这里实现的机制本应防止具有挂载权限的用户挂载到他们不拥有的目录(如/etc或/System)。如果挂载点存在但不归用户所有,则会产生kDAReturnNotPermitted错误代码。这里存在一个典型的检查时间与使用时间(TOCTOU)问题:如果在检查之后但在挂载之前创建挂载点,即使调用者不拥有挂载点,挂载也可能成功。

构建本地管理员到root的利用

我们可以使用以下伪代码利用此漏洞将任何磁盘挂载到/etc:

1
2
3
4
5
6
7
8
9
disk = "/dev/some-disk-device"

in the background:
  while true:
    create symlink "/tmp/foo" pointing to "/"
    remove symlink

while disk not mounted at "/etc":
  send IPC request to diskarbitrationd to mount disk to "/tmp/foo/etc"

最终,检查将在符号链接不存在时执行,但挂载将在符号链接存在时发生,因此两者都会通过。此时我们已经挂载到了/etc,这对于本地管理员用户来说通常是不可能的。

我们使用MacBook上的EFI分区(/dev/disk0s1)作为可写设备,并通过在/var/at/tabs/root中创建crontab文件来获得root权限执行任意命令。

从Safari触发漏洞

要在沙箱中触发此漏洞,我们需要:

  1. 访问diskarbitrationd的IPC端点 - 已满足
  2. 对任意目录的写访问权限 - 已满足
  3. 获取挂载的授权令牌 - 不满足
  4. 创建符号链接的能力 - 不满足

在系列的下一部分中,我们将介绍另外三个漏洞,其中一个用于创建符号链接,另外两个用于绕过授权逻辑中的沙箱检查。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计