Sie sind an Cloud Computing interessiert? Legen Sie jetzt los

Ich kann es kaum erwarten, Sie stillzulegen – Remote-DoS mit Wininit.exe

Stiv Kupchik

Verfasser

Stiv Kupchik

January 31, 2023

Stiv Kupchik

Verfasser

Stiv Kupchik

Stiv Kupchik ist Senior Security Researcher in Tel Aviv, Israel.

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).

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: 

Exponierte Funktionen von WindowsShutdown: WsdrInitiateShutdown, WsdrAbortShutdown und WsdrCheckForHiberboot Abb. 1: Die Funktionen der WindowsShutdown-Schnittstelle

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.

Dekompilierung der Sicherheitscallback-Funktion für WindowsShutdown Abb. 2: Sicherheitscallback für WindowsShutdown

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.

advapi32 Disassemblierung von CheckForHiberboot Abb. 3: Die advapi CheckForHiberboot – der einzige dokumentierte RPC-Client, den wir für WsdrCheckForHiberboot gefunden haben

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.

Erste Neuerstellung der WsdrCheckForHiberboot-Definition auf Basis der advapi-Funktion Abb. 4: Die erste Neuerstellung der WsdrCheckForHiberboot-Definition

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:

Erste Neuerstellung der WsdrCheckForHiberboot-Definition auf Basis der advapi-Funktion Abb. 5: Der Abschnitt von WsdrCheckForHiberboot aus dem ProcFormatString

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.



Stiv Kupchik

Verfasser

Stiv Kupchik

January 31, 2023

Stiv Kupchik

Verfasser

Stiv Kupchik

Stiv Kupchik ist Senior Security Researcher in Tel Aviv, Israel.