【DEFCON & HITB】Bug Hunting In VMware Device Virtualization(下篇)
本文是天工实验室在DEFCON上发表的议题《Dragon Slaying Guide: Bug Hunting in VMware Device Virtualization》的第三部分内容。在该议题的前两篇文章中,分别介绍了VMware虚拟化实现和虚拟USB设备漏洞挖掘。 本周将继续讲解议题最后一个部分:SCSI Device Virtualization。主要介绍虚拟磁盘系统SCSI相关设备模拟在VMware Workstation和ESXI下的异同,以及我们在VMKernel中发现的有关磁盘设备模拟的设计缺陷。 一、前言 磁盘设备的代码架构和USB设备类似,首先他有许多作为前端的主机控制器设备模拟代码,比如 LsiLogic,NVME,PVSCSI,AHCI,有趣的地方在与作为连同主机控制器与磁盘设备的中间层代码实际上只处理SCSI协议指令,VMware为每种主机控制器都设计了用于将主机控制器请求翻译成SCSI请求的代码,所有不同磁盘设备的主机控制器请求在最终都会被统一成SCSI指令,后端设备模拟代码同样使用了类似面向对象的设计,从基本的SCSI设备对象可以派生出各种不同类型的设备,CDROM,Disk 等等。 无论是Esxi还是Workstation的 vmx 都有几乎一样的处理代码,但真正引起我们注意的是 Esxi 在默认情况下并没有使用 vmx 中对磁盘请求处理的代码,只有在启用了 HostEmulated 配置时,才会由vmx负责处理。 通过前文对 vmm 部分的分析,我们发现Esxi默认情况下正是通过 vmm 中对 VMKernel 的调用使用 VMKernel 中对应的模拟代码进行处理,这很快就引起了我们的兴趣,在 VMKernel 的范围下,哪怕是出现断言错误都可能带来整个 Hypervisor 的瘫痪,从而引起单个Esxi上所有客户机拒绝服务。 二、漏洞一:CVE-2024-22273:Out-of-bounds Read/Write 关于磁盘部分的第一个漏洞,如果按照控制器-后端设备模型来看,它处于后端设备模拟部分。 VMware会将所有请求在模拟阶段统一转化为SCSI指令,接着解析你访问的磁盘ID,根据磁盘ID来将SCSI指令转发到对应的设备上。转发这一过程,在VMware中有一个专门的函数进行处理,我们将其称为SCSIDevice_Dispatch。在SCSIDevice_Dispatch函数中,首先会解析你SCSI指令中的CDB部分,判断CDB请求是否符合要求。处理完CDB请求后,会来到我们将其称为HBAHosted_PostIo的函数中。 该函数中有一段特别的代码逻辑,这段代码逻辑可以理解为磁盘验证器功能,磁盘验证器负责检测磁盘是否存在坏扇区。验证原理如下:硬盘以块为单位(扇区)写入数据,硬盘每次更新扇区时,也会更新校验和(紧接在扇区数据之后存储)。当从硬盘驱动器读取扇区时,预计扇区校验和将与扇区数据匹配,如果不匹配,则表示磁盘在写入操作期间出现了问题,存在坏扇区。 VMware的磁盘验证器代码中,申请了一块等价磁盘大小的堆作为校验和的存储内容,对磁盘进行访问操作时(Read/Write),磁盘验证器并没有对命令中访问扇区的边界做任何检测与限制,直接计算用户访问的目标扇区的校验和并将其写入对应内存,这就导致了用户访问的目标扇区可能超出磁盘的扇区上限,引发严重的堆越界访问问题。 又因为CDB命令中,读写指令的最大范围为Write16/Read16。 即允许访问的扇区数最大数据类型为uint64,从而形成了骇人听闻的任意写漏洞。 该漏洞同时存在于Workstation/Esxi中,但对应的触发路径不尽相同。在Workstation中,可以从CD/ROM或SCSI磁盘两个方面分别去触发该漏洞;但在Esxi中,只能从CD/ROM去触发漏洞,无法从SCSI磁盘角度去触发。 因为在Esxi中,VMM会判断主机是否处于hostedEmulation模式,如果处于,就将请求通过UserRPC发送到VMX中处理,如果不处于,就将请求通过vmkcall发送到VMKernel,这就导致了在Esxi的磁盘设备上无法触发该漏洞。 当然,正因为Esxi会将磁盘请求发送到VMKernel中去处理,这也引出了后续关于VMKernel中磁盘的漏洞。 三、漏洞二:CVE-2024-37086:Out-of-bounds Read 我们发现,VMware在VMKernel中对发送来的磁盘请求处理已经尽可能的小心翼翼,禁用了许多不必要的SCSI命令,只启用小部分必要的SCSI命令。但即使是在如此谨慎的情况下,被启用的SCSI命令中依然存在严重的设计问题。 SCSI命令中的UNMAP命令允许一个或多个LBA(Logical Block Address)被取消映射,该命令常用在精简配置技术中,以提高存储利用率、灵活的容量规划和不间断存储配置服务。 在SPC-6(SCSI Primary Commands - 6)中对于UNMAP命令的设计如下图所示: 先来解释一下图里重要的数据结构: Table 204 UNMAP command中最重要的字段为PARAMETER LIST LENGTH,表示应用客户端发送到设备服务器的 UNMAP 参数数据的长度...