
Proof-of-Concept für CVE-2021-28476, eine beliebige Zeiger-Dereferenzierung in Hyper-V vmswitch.sys, die einen Denial-of-Service vom Gast zum Host sowie potenzielles RCE ermöglicht.
Eine Hyper-V-Gast-VM kann auf ihrem zugrunde liegenden Host eine Denial-of-Service-Bedingung auslösen, da die Funktion VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST in vmswitch.sys Eingaben unsicher parst. Der Absturz wird dadurch verursacht, dass die Funktion versucht, einen vom Gast kontrollierten Wert zu dereferenzieren, als wäre es eine Host-Virtual-Adresse. Dieser Fehler kann unter bestimmten Bedingungen zur Erlangung von RCE genutzt werden, nämlich wenn die Anfrage mit einem Zeiger auf vom Angreifer kontrollierte Daten an ein zugrunde liegendes Hardwaregerät weitergeleitet wird. Mir ist jedoch nicht bekannt, dass diese Technik öffentlich demonstriert wurde.
https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-28476
Beliebige Dereferenzierung
Reverse Engineering/Code-Audit
Dieser Fehler wurde während meiner ersten Erkundung des vmswitch-Treibers gefunden. Bei der Durchsicht der Dokumentation auf MSDN wurde festgestellt, dass die Struktur NDIS_SWITCH_NIC_OID_REQUEST einen Zeiger enthält, und ich erinnerte mich, in einem Funktionsnamen einen Verweis auf den Strukturnamen gesehen zu haben. Es wurde etwas Reverse Engineering durchgeführt, um zu verstehen, wie die Funktion funktionieren könnte, da ein Gast keine Kenntnis von der Host-VA haben sollte, aber keine echten Sicherheitsprüfungen vorhanden waren. Anschließend wurde ein modifizierter Linux-Hyper-V-Treiber verwendet, um eine gefälschte Anfrage an den Host zu senden, was sofort einen Absturz auslöste.
Der Treiber vmswitch.sys enthält eine Reihe von Funktionen zur Verarbeitung von RNDIS-OID-Anfragen, darunter auch einige, die speziell zum Protokollieren eingehender Nachrichten dienen. Eine davon, VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST, verarbeitet Anfragen vom Typ OID_SWITCH_NIC_REQUEST. Laut MSDN-Dokumentation ist diese Anfrage dazu gedacht, die Weiterleitung von OID-Anfragen von einer Gastmaschine an einen zugrunde liegenden physischen Netzwerkadapter über den externen Netzwerkadapter der Hyper-V-erweiterbaren Switch zu ermöglichen.
OID-Anfragen verwenden für ihre äußere Schicht eine klar definierte, generische Nachrichtenstruktur, die einen "InformationBuffer" enthält, der Daten speichern soll, die für einen bestimmten OID-Nachrichtentyp spezifisch sind. Im Fall von OID_SWITCH_NIC_REQUEST hat der InformationBuffer die folgende Definition (beachten Sie, dass diese geringfügig von der dokumentierten Struktur abweicht, aber dem entspricht, was funktional im Code vorhanden war):
typedef struct _NDIS_SWITCH_NIC_OID_REQUEST {
NDIS_OBJECT_HEADER Header; //u32 große Struktur
u32 Flags;
NDIS_SWITCH_PORT_ID SourcePortId; //u32 Typ
NDIS_SWITCH_PORT_NIC SourceNicIndex; //u32 Typ
NDIS_SWITCH_PORT_ID DestinationPortId; //u32 Typ
NDIS_SWITCH_PORT_NIC DestinationNicIndex; //u32 Typ
PNDIS_OID_REQUEST OidRequest; //**sollte** ein Zeiger auf eine weitergeleitete NDIS_OID_REQUEST-Struktur sein
} NDIS_SWITCH_NIC_OID_REQUEST, *PNDIS_SWITCH_NIC_OID_REQUEST;
Als Teil der anfänglichen Verarbeitung dieses Objekts versucht VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST, die weitergeleitete NDIS_OID_REQUEST-Anfrage aus der umschließenden _NDIS_SWITCH_NIC_OID_REQUEST zu entpacken. Wenn jedoch eine Hyper-V-Gast-VM einen ungültigen Speicherort als OidRequest-Wert liefert, verursacht die Dereferenzierung einen Out-of-Bounds-Read und stürzt den Kernel der Root-Partition ab.
Pseudocode der betroffenen Funktion sieht wie folgt aus:
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; //Dereferenzierung und Absturz erfolgen hier
}
}
...
//abgeschnitten
...
return;
}