CVE-2020-0069 MediaTek-SU提权漏洞分析

一、漏洞背景

  • Google在2020-03的Android安全公告中,指出了一个联发科芯片手机中的严重安全漏洞,成功利用此漏洞的攻击者可以取得设备的root权限。由于取得了极高的权限,所以攻击者可以进一步实施其它的恶意行为,并且用户毫不知情。漏洞被命名为MediaTek-SU,并以CVE-2020-0069来跟踪。
  • 值得注意的是,XDA-Developers在其报告中写到,早在2019年4月,他们就已经知晓了此事。

二、漏洞细节

  • 在搭载联发科芯片的智能手机上存在命令队列驱动程序/dev/cmdq,该驱动程序具备读写任意内存的功能,代码位于/drivers/misc/mediatek/cmdq/hv1/cmdq_driver.ccmdq_ioctl函数中:
static long cmdq_ioctl(struct file *pFile, unsigned int code, unsigned long param) {
    // ...
    switch(code) {
        // ...
        case CMDQ_IOCTL_ALLOC_WRITE_ADDRESS:
            do {
                struct cmdqWriteAddressStruct addrReq;
                dma_addr_t paStart = 0;
                CMDQ_LOG("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS\n");
                if (copy_from_user(&addrReq, (void *)param, sizeof(addrReq))) {
                    CMDQ_ERR("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS copy_from_user failed\n");
                    return -IOCTL_RET_COPY_ALLOC_WRITE_ADDR_FROM_USER_FAIL;
                }
                status = cmdqCoreAllocWriteAddress(addrReq.count, &paStart);
                if (0 != status) {
                    CMDQ_ERR("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS cmdqCoreAllocWriteAddress() failed\n");
                    return -IOCTL_RET_ALLOC_WRITE_ADDR_FAIL;
                }
                addrReq.startPA = (uint32_t) paStart;
                CMDQ_LOG("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS get 0x%08x\n", addrReq.startPA);
                if (copy_to_user((void *)param, &addrReq, sizeof(addrReq))) {
                    CMDQ_ERR("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS copy_to_user failed\n");
                    return -IOCTL_RET_COPY_ALLOC_WRITE_ADDR_TO_USER_FAIL;
                }
                status = 0;
            } while (0);
            break;
        case CMDQ_IOCTL_READ_ADDRESS_VALUE:
            do {
                struct cmdqReadAddressStruct readReq;
                CMDQ_LOG("CMDQ_IOCTL_READ_ADDRESS_VALUE\n");
                if (copy_from_user(&readReq, (void *)param, sizeof(readReq))) {
                    CMDQ_ERR("CMDQ_IOCTL_READ_ADDRESS_VALUE copy_from_user failed\n");
                    return -IOCTL_RET_COPY_READ_ADDR_FROM_USER_FAIL;
                }
                /* this will copy result to readReq->values buffer*/
                cmdq_driver_process_read_address_request(&readReq);
                status = 0;
            } while (0);
            break;
        // ...
    }
    // ...
}
  • 由于该驱动程序结点的权限配置错误,导致任意应用都可以通过ioctl系统调用访问该驱动程序,并且读写任意内存,从而获得root权限。
  • 在实际测试过程中发现,联发科将/dev/cmdq的SELinux标签配置为了mtk_cmdq_device,又将该标签的openreadioctl系统调用操作权限赋予给了appdomain域。由于所有Android应用程序都位于appdomain域中,所以就导致任意应用程序可利用该驱动程序提升自身权限到root。

三、漏洞验证

  • 在XDA-Developers论坛上,已经给出了PoC,直接在adb shell中执行即可获得root权限,其源代码并未公开,不过基本的利用原理就是通过ioctl系统调用访问/dev/cmdq来读写内存。
  • 该漏洞影响的内核版本:Linux Kernel 3.18, 4.4, 4.9, 4.14
  • 该漏洞影响的联发科芯片型号:MT6580, MT6595, MT6735, MT6737, MT6738, MT6739, MT6750, MT6753, MT6755, MT6757, MT6758, MT6761, MT6762, MT6763, MT6765, MT6771, MT6779, MT6795, MT6797, MT6799, MT8163, MT8167, MT8173, MT8176, MT8183

四、漏洞影响

  • 任意第三方应用程序都可以利用此漏洞获得root权限,甚至可以关闭SELinux,从而完全控制整个手机。

五、漏洞补丁

  • Google已经在2020-03的Android安全公告中已经修复了该漏洞,其Android安全补丁级别为2020-03-05,关于补丁的细节暂未发布。