
Proof-of-concept per CVE-2021-28476, un dereferenziamento arbitrario di puntatore in Hyper-V vmswitch.sys che consente denial-of-service da guest a host e potenziale RCE.
Una macchina virtuale guest di Hyper-V può innescare una condizione di Denial-of-Service sul proprio host sottostante a causa di un parsing non sicuro dell'input da parte della funzione VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST in vmswitch.sys. Il crash è causato dal tentativo della funzione di dereferenziare un valore controllato dal guest come se fosse un indirizzo virtuale dell'host. Questo bug può essere utilizzato per ottenere RCE in alcune condizioni, in particolare quando la richiesta viene passata a un dispositivo hardware sottostante con un puntatore a dati controllati dall'attaccante, tuttavia non sono a conoscenza che questa tecnica sia stata dimostrata pubblicamente.
11 maggio 2021
https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-28476
Dereferenziamento arbitrario
Reverse Engineering/Audit del codice
Questo bug è stato trovato durante la mia ricognizione iniziale del driver vmswitch. Durante la revisione della documentazione su MSDN è stato notato che la struttura NDIS_SWITCH_NIC_OID_REQUEST conteneva un puntatore, e ho ricordato di aver visto un riferimento al nome della struttura in un nome di funzione. È stato eseguito un po' di reverse engineering per cercare di capire come la funzione potesse operare, dato che un guest non dovrebbe avere alcuna conoscenza del VA dell'host ma non erano presenti controlli di sicurezza reali. Un driver Linux Hyper-V modificato è stato quindi utilizzato per inviare una richiesta falsa all'host, innescando immediatamente un crash.
Il driver vmswitch.sys contiene una serie di funzioni per gestire le richieste OID RNDIS, incluse alcune specificamente progettate per registrare i messaggi in arrivo. Una di queste, VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST, gestisce le richieste di tipo OID_SWITCH_NIC_REQUEST. Secondo la documentazione MSDN, questa richiesta è progettata per consentire l'inoltro delle richieste OID da una macchina guest a un adattatore di rete fisico sottostante tramite l'adattatore di rete esterno dello switch estensibile Hyper-V.
Le richieste OID utilizzano una struttura di messaggio generica e ben definita per il loro livello esterno, che include un "InformationBuffer" progettato per contenere dati specifici di un tipo di messaggio OID. Nel caso di OID_SWITCH_NIC_REQUEST, l'InformationBuffer ha la seguente definizione (nota che questa differisce leggermente dalla struttura documentata, ma corrisponde a ciò che era funzionalmente presente nel codice):
typedef struct _NDIS_SWITCH_NIC_OID_REQUEST {
NDIS_OBJECT_HEADER Header; //struct di dimensione 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; //**dovrebbe** essere un puntatore a una struttura NDIS_OID_REQUEST inoltrata
} NDIS_SWITCH_NIC_OID_REQUEST, *PNDIS_SWITCH_NIC_OID_REQUEST;
Come parte del parsing iniziale di questo oggetto, VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST tenterà di estrarre la richiesta NDIS_OID_REQUEST inoltrata dalla struttura incapsulante _NDIS_SWITCH_NIC_OID_REQUEST. Tuttavia, se un guest Hyper-V fornisce una posizione di memoria non valida come valore di OidRequest, il dereferenziamento causerà una lettura fuori dai limiti e un crash del kernel della partizione root.
Lo pseudo-codice della funzione interessata è il seguente:
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; //il dereferenziamento e il crash avvengono qui
}
}
...
//troncato
...
return;
}