
Prueba de concepto para CVE-2021-28476, una desreferencia de puntero arbitrario en Hyper-V vmswitch.sys que permite denegación de servicio de invitado a host y posible RCE.
Una máquina virtual invitada de Hyper-V puede desencadenar una condición de Denegación de Servicio en su host subyacente debido al análisis inseguro de entrada por parte de la función VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST en vmswitch.sys. El fallo es causado por la función que intenta desreferenciar un valor controlado por el invitado como si fuera una dirección virtual del host. Este error puede usarse para obtener RCE bajo algunas condiciones, concretamente cuando la solicitud se pasa a un dispositivo de hardware subyacente con un puntero a datos controlados por el atacante; sin embargo, no tengo conocimiento de que esta técnica haya sido demostrada públicamente.
11 de mayo de 2021
https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-28476
Desreferencia arbitraria
Ingeniería inversa/Auditoría de código
Este error fue encontrado durante mi reconocimiento inicial del controlador vmswitch. Al revisar la documentación en MSDN, se observó que la estructura NDIS_SWITCH_NIC_OID_REQUEST contenía un puntero, y recordé haber visto una referencia al nombre de la estructura en un nombre de función. Se realizó algo de ingeniería inversa para intentar entender cómo podría operar la función, dado que un invitado no debería tener ningún conocimiento de la VA del host, pero no había comprobaciones de seguridad reales presentes. Luego se usó un controlador Linux Hyper-V modificado para enviar una solicitud falsa al host, lo que inmediatamente provocó un fallo.
El controlador vmswitch.sys contiene una serie de funciones para manejar solicitudes OID de RNDIS, incluyendo algunas específicamente para registrar mensajes entrantes. Una de estas, VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST, maneja solicitudes de tipo OID_SWITCH_NIC_REQUEST. Según la documentación de MSDN, esta solicitud está diseñada para permitir el reenvío de solicitudes OID desde una máquina invitada a un adaptador de red físico subyacente a través del adaptador de red externo del conmutador extensible de Hyper-V.
Las solicitudes OID usan una estructura de mensaje genérica y bien definida para su capa externa, que incluye un "InformationBuffer" diseñado para contener datos específicos de un tipo de mensaje OID. En el caso de OID_SWITCH_NIC_REQUEST, el InformationBuffer tiene la siguiente definición (nótese que difiere ligeramente de la estructura documentada, pero coincide con lo que estaba funcionalmente presente en el código):
typedef struct _NDIS_SWITCH_NIC_OID_REQUEST {
NDIS_OBJECT_HEADER Header; //estructura de tamaño u32
u32 Flags;
NDIS_SWITCH_PORT_ID SourcePortId; //tipo u32
NDIS_SWITCH_PORT_NIC SourceNicIndex; //tipo u32
NDIS_SWITCH_PORT_ID DestinationPortId; //tipo u32
NDIS_SWITCH_PORT_NIC DestinationNicIndex; //tipo u32
PNDIS_OID_REQUEST OidRequest; //**debería** ser un puntero a una estructura NDIS_OID_REQUEST reenviada
} NDIS_SWITCH_NIC_OID_REQUEST, *PNDIS_SWITCH_NIC_OID_REQUEST;
Como parte del análisis inicial de este objeto, VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST intentará desenvolver la solicitud NDIS_OID_REQUEST reenviada desde la estructura encapsuladora _NDIS_SWITCH_NIC_OID_REQUEST. Sin embargo, si un invitado de Hyper-V suministra una ubicación de memoria inválida como valor de OidRequest, la desreferencia causará una lectura fuera de los límites y bloqueará el kernel de la partición raíz.
El pseudo-código de la función afectada es el siguiente:
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; //la desreferencia y el fallo ocurren aquí
}
}
...
//truncado
...
return;
}