Hyper-V 客户虚拟机可因其 vmswitch.sys 中的 VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST 函数对输入的不安全解析,而在其底层宿主机上触发拒绝服务(Denial-of-Service)条件。该崩溃是由函数试图将客户机控制的值当作宿主机虚拟地址进行解引用所致。在某些条件下,此漏洞可能被用于获取远程代码执行(RCE),即当请求连同指向攻击者控制数据的指针被传递给底层硬件设备时,但据我所知,该技术尚未被公开演示。
2021年5月11日
https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-28476
任意解引用
逆向工程/代码审计
此漏洞是在我对 vmswitch 驱动程序的初步侦察过程中发现的。在查阅 MSDN 上的文档时,我注意到 结构体包含一个指针,并且我回想起曾在某个函数名称中看到过该结构体名称的引用。随后进行了一些逆向工程,以尝试理解该函数可能如何运作,考虑到客户机不应知晓宿主机虚拟地址,但代码中并未存在真正的安全检查。随后,使用修改过的 Linux Hyper-V 驱动程序向宿主机发送了一个伪造请求,立即触发了崩溃。
NDIS_SWITCH_NIC_OID_REQUESTvmswitch.sys 驱动程序包含多个用于处理 RNDIS OID 请求的函数,其中一些专门用于记录传入消息。其中一个函数 VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST 处理 OID_SWITCH_NIC_REQUEST 类型的请求。根据 MSDN 文档,此请求旨在允许通过 Hyper-V 可扩展交换机外部网络适配器,将 OID 请求从客户机转发至底层物理网络适配器。
OID 请求在其外层使用一种定义明确、通用的消息结构,其中包含一个“InformationBuffer”,用于保存特定于某 OID 消息类型的数据。对于 OID_SWITCH_NIC_REQUEST,InformationBuffer 的定义如下(请注意,这与文档中的结构略有不同,但与代码中实际存在的功能相符):
typedef struct _NDIS_SWITCH_NIC_OID_REQUEST {
NDIS_OBJECT_HEADER Header; //u32 大小的结构体
u32 Flags;
NDIS_SWITCH_PORT_ID SourcePortId; //u32 类型
NDIS_SWITCH_PORT_NIC SourceNicIndex; //u32 类型
NDIS_SWITCH_PORT_ID DestinationPortId; //u32 类型
NDIS_SWITCH_PORT_NIC DestinationNicIndex; //u32 类型
PNDIS_OID_REQUEST OidRequest; //**应当**是指向被转发 NDIS_OID_REQUEST 结构体的指针
} NDIS_SWITCH_NIC_OID_REQUEST, *PNDIS_SWITCH_NIC_OID_REQUEST;
作为对此对象初始解析的一部分,VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST 将尝试从封装的 _NDIS_SWITCH_NIC_OID_REQUEST 中解包被转发的 NDIS_OID_REQUEST 请求。然而,如果 Hyper-V 客户机提供一个无效的内存位置作为 OidRequest 值,该解引用将导致越界读取并使根分区内核崩溃。
受影响函数的伪代码如下:
void VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST(void* unknown1, u64 unknown2, _NDIS_SWITCH_NIC_OID_REQUEST* request, u32 buffer_size) {
NDIS_OID_REQUEST* forwarded_request;
if((unknown1 != 0) && (buffer_size != 0)) {
if(buffer_size > 0x20) {
forwarded_request = (NDIS_OID_REQUEST*)request->OidRequest; //解引用并在此处发生崩溃
}
}
...
//已截断
...
return;
}