Ich kann es kaum erwarten, Sie stillzulegen – Remote-DoS mit Wininit.exe
Redaktion und weitere Beiträge von Tricia Howard
Zusammenfassung
Der Akamai-Forscher Stiv Kupchik hat eine neue DoS-Schwachstelle (Denial of Service) in der Datei wininit.exe von Microsoft, CVE-2022-44707, mit einem CVSS-Wert von 6,5 entdeckt.
Die Schwachstelle wurde MSRC im August offengelegt und im Rahmen des Patch Tuesday vom Dezember 2022 behoben.
Die Schwachstelle nutzt den RPC-Caching-Mechanismus aus, an dem wir umfangreiche Untersuchungen durchgeführt haben. Einen Proof of Concept des Angriffs haben wir in unserem RPC-Toolkitdargelegt.
Durch Ausnutzung dieser Sicherheitslücke kann ein Angreifer mithilfe des Caching-Mechanismus die Sicherheitsprüfung umgehen und mit dem Abschaltmechanismus auf einem Windows-Remotecomputer interagieren – so erhält er die Kontrolle über Abschaltprozesse und kann diese starten oder stoppen.
Die Schwachstelle betrifft alle nicht gepatchten Windows-Versionen ab Windows 8/Server 2012, was die Wichtigkeit eines zeitnahen Patches unterstreicht.
Einführung
In unserem vorherigen Beitrag, Cold Hard Cache, haben wir einige weitere RPC-Schwachstellen erwähnt, die wir mit unserem RPC-Toolkit entdeckt haben, und es ist Zeit, diese endlich offenzulegen. Heute geht es um Wininit.
Wininit ist ein wichtiger Windows-Prozess, der sowohl beim Starten als auch beim Herunterfahren des Betriebssystems eine große Rolle spielt (im Sinne von: Wenn Wininit abstürzt, stürzt das gesamte System ab). Daher ermöglicht es den Zugriff auf mehrere RPC-Schnittstellen, die die Abschaltfunktion bereitstellen – einige davon sind sogar dokumentiert. Die Schwachstelle, die wir gefunden haben, betrifft die WindowsShutdown- Schnittstelle.
Was ist die WindowsShutdown-Schnittstelle?
WindowsShutdown ist eine der wenigen RPC-Schnittstellen, auf die wininit Zugriff bietet. Sie ist für das Herunterfahren verantwortlich (wie auch die übrigen RPC-Schnittstellen von wininit – welch Überraschung). Die UUID der Schnittstelle ist d95afe70-a6d5-4259-822e-2c84da1ddb0d. Sie ist Teil von MS-RSP (Remote Shutdown Protocol) und verfügt über die folgenden Funktionen:
Wenn wir uns die öffentliche IDL-Datei ansehen, sehen wir, dass nur WsdrInitiateShutdown und WsdrAbortShutdown dokumentiert sind. Sollten wir uns über undokumentierte Funktionen Gedanken machen (das hat sich bestimmt noch kein Forscher vor uns gefragt)? Um dies zu beantworten, schauen wir uns den Sicherheitscallback für diese Schnittstelle an.
Der Sicherheitscallback
Der Callback prüft zuerst das Transportprotokoll und lässt nur ALPC oder TCP zu. Anschließend wird die Authentifizierungsebene geprüft und nur RPC_C_AUTHN_LEVEL_PKT_PRIVACY zugelassen. Wenn die aufgerufene Funktion nicht WsdrCheckForHiberboot ist, wird das Token des anfragenden Remote-Nutzers geprüft. Dies erfolgt durch den Vergleich des Tokens mit einer bekannten SID (in einer globalen Variable gespeichert, die während der Initialisierung von wininit erstellt wurde – SECURITY_NETWORK_RID EIN. Anfragen an WsdrCheckForHiberboot sind durch den Sicherheitscallback überhaupt nicht eingeschränkt.
Die RPC-Schnittstelle ist mit dem standardmäßigen Cache-Verhalten registriert, also können wir theoretisch, wenn wir WsdrCheckForHiberbooterfolgreich aufrufen können, mit dem im Cache gespeicherten Ergebnis die SID-Prüfung bei nachfolgenden Aufrufen von WsdrInitiateShutdown und WsdrAbortShutdownumgehen.
Was müssen wir tun, um WsdrCheckForHiberbootaufzurufen?
WsdrCheckForHiberboot
Uns ist nicht wirklich wichtig, was die Funktion tut oder was der Hiberboot ist (es ist der Windows-Schnellstart, falls Sie es wissen wollen), aber wir müssen verstehen, wie man sie richtig aufruft. Wir wollen die Funktion in einer IDL-Datei korrekt definieren, um dafür einen Client zu kompilieren. Obwohl die Funktionalität nicht dokumentiert ist, können wir versuchen, uns die advapi CheckForHiberbootanzusehen – den einzigen dokumentierten RPC-Client, den wir für WsdrCheckForHiberbootgefunden haben. Es sind nur zwei Argumente erforderlich: Ein boolescher Pointer und ein boolescher Wert.
Mit diesen Argumenten können wir die Funktionsdefinition neu erstellen, indem wir eine IDL-Datei und ein Programm kompilieren. Aber leider fehlt uns noch etwas. Beim Remote-Aufruf der Funktion mit unserem Client teilt uns die RPC-Laufzeit mit, dass wir die Funktion falsch aufrufen, indem sie einen RPC-Stub-Fehler zurückgibt.
Anstatt uns mit noch mehr Rätselraten herumzuschlagen, können wir zu einer besseren aber aufwändigen Methode greifen: Der RPC- Schnittstellen-Stubverfügt über das Feld ProcFormatString. Es handelt sich im Grunde um eine lange binäre Zeichenfolge, die die Argumenttypen und die Rückgabewerte für alle Funktionen beschreibt, auf die die Schnittstelle Zugriff hat. Dieses Feld wird von der RPC-Laufzeit beim Marshalling und Unmarshalling der Funktionsaufrufe verwendet (der Prozess, der bei unserem ersten Versuch den RPC-Stub-Fehler zurückgegeben hat). Durch mühsames manuelles Parsing dieser Binärzeichenfolge fanden wir schließlich heraus, dass es ein weiteres Argument gibt, das die Funktion erwartet – und zwar vom Typ wchar_t*. In der nächsten Abbildung sehen Sie den Abschnitt von ProcFormatString aus WsdrCheckForHiberbootmit unseren Kommentaren:
Nach dem Hinzufügen des „neuen“ Arguments zu unserer Funktionsdefinition läuft alles glatt! CheckForHiberboot wird erfolgreich zurückgegeben und wir können jetzt WsdrInitiateShutdown und WsdrAbortShutdownaufrufen.
Gleich ist es geschafft
Als Erstes möchten wir den Caching-Angriff nutzen, um WsdrInitiateShutdown aufzurufen und einen Remote Shutdown vorzunehmen. Diesmal ist kein Rätselraten nötig. Die Funktionsdefinition ist nicht nur in der IDL-Datei dokumentiert, sondern auch die Flags, die sie erwartet, werden unter der advapi-Funktion InitiateShutdownAaufgelistet. Mit der Flag-Kombination aus SHUTDOWN_GRACE_OVERRIDE, SHUTDOWN_HYBRID und SHUTDOWN_FORCE_OTHERS können wir also ein sofortiges Herunterfahren erzwingen.
Damit haben wir unsere Angriffskette abgeschlossen: Wir können den Sicherheitscallback und die SID-Prüfung umgehen und einen Remote Shutdown erzwingen. Technisch gesehen handelt es sich hierbei um eine Eskalation von Berechtigungen (sodass jeder authentifizierte Nutzer WsdrInitiateShutdown per Remote-Zugriff aufrufen kann, anstatt nur die Berechtigungen zu erhalten, die unter SECURITY_NETWORK_RID EINzulässig sind). Da wir das System nur über diese Schnittstelle herunterfahren können, wurde die Schwachstelle stattdessen als DoS-Schwachstelle kategorisiert.
Erkennung
Wir stellen Ihnen eine OSQuery zur Verfügung, um ungepatchte (und somit anfällige) Versionen von wininit.exe zu erkennen. Kunden von Akamai Guardicore Segmentation können die Insight-Funktion zusammen mit dieser Abfrage verwenden, um nach anfälligen Assets zu suchen.
WITH product_version AS (
WITH os_minor AS (
WITH os_major AS (
SELECT substr(product_version, 0, instr(product_version, ".")) as os_major, substr(product_version, instr(product_version, ".")+1) as no_os_major_substr
FROM file
WHERE path = "c:\windows\system32\wininit.exe"
)
SELECT substr(no_os_major_substr, instr(no_os_major_substr, ".")+1) as no_os_minor_substr, substr(no_os_major_substr, 0, instr(no_os_major_substr, ".")) as os_minor, os_major
FROM os_major
)
SELECT
CAST(substr(no_os_minor_substr, instr(no_os_minor_substr, ".")+1) AS INTEGER) AS product_minor,
CAST(substr(no_os_minor_substr, 0, instr(no_os_minor_substr, ".")) AS INTEGER) AS product_major,
CAST(os_minor AS INTEGER) AS os_minor,
CAST(os_major AS INTEGER) AS os_major
FROM os_minor
)
SELECT
CASE
WHEN NOT ((os_major = 6 AND os_minor = 3) OR (os_major = 6 AND os_minor = 2) OR (os_major = 10 AND os_minor = 0))
THEN "not supported"
WHEN os_major = 6 AND os_minor = 3 AND product_major = 9600 AND product_minor >= 20716 THEN "patched"
WHEN os_major = 6 AND os_minor = 2 AND product_major = 9200 AND product_minor >= 24011 THEN "patched"
WHEN (
(product_major = 14393 AND product_minor >= 5582)
OR
(product_major = 10240 AND product_minor >= 19624)
OR
(product_major = 19041 AND product_minor >= 1620)
OR
(product_major = 22621 AND product_minor >= 963)
OR
(product_major = 22000 AND product_minor >= 1335)
OR
(product_major = 20348 AND product_minor >= 1366)
OR
(product_major = 17763 AND product_minor >= 3770)
)
THEN
"patched"
ELSE
"not patched"
Zusammenfassung
Obwohl diese Schwachstelle nicht kritisch ist (es ist nur ein Remote Shutdown, und nicht einmal ein nicht authentifizierter), zeigt es das zerstörerische Potenzial von MS-RPC auf, da es selbst in die wichtigsten Services des Windows-Betriebssystems integriert ist. Im Gegensatz zu anderen Arten von Schwachstellen gibt es bei RPC fast kein Rätselraten – alle Karten liegen auf dem (binären) Tisch; Sie müssen nur wissen, wie sie zu entziffern sind.
Die Suche nach Möglichkeiten, diese kritischen Funktionen zu nutzen, ist genau der Grund, warum wir unsere umfangreiche Forschung zu MS-RPCfortsetzen. Trotz seiner weiten Verbreitung und Nutzung wird es im Großen und Ganzen kaum untersucht. Schwachstellen wie die heute vorgestellte zeigen, warum diese Art von Arbeit notwendig ist, und wir freuen uns darauf, auch andere Forscher an MS-RPC arbeiten zu sehen.
Diese Schwachstelle wurde Ende August verantwortungsvoll an Microsoft weitergegeben und am Patch Tuesday vom Dezember 2022 behoben.