Sie sind an Cloud Computing interessiert? Legen Sie jetzt los

Sie haben eine Grenze überschritten – Die Störung der Ruhe eines Hosts

Akamai Wave Blue

Verfasser

Ben Barnea

December 14, 2022

Akamai Wave Blue

Verfasser

Ben Barnea

Ben Barnea ist Sicherheitsforscher bei Akamai. Sein Fachgebiet ist die Durchführung von Sicherheits- und Schwachstellenforschung auf niedriger Ebene über verschiedene Architekturen hinweg, einschließlich Windows, Linux, Internet of Things und Mobilgeräten. Er lernt gerne, wie komplexe Mechanismen funktionieren und, was viel wichtigster ist, warum sie ausfallen.

MS-RPC ist noch weitgehend unerforscht, und das kann reale Auswirkungen haben. Eine dieser Auswirkungen ist, dass Schwachstellen in einer RPC-Schnittstelle aufgedeckt werden.
MS-RPC ist noch weitgehend unerforscht, und das kann reale Auswirkungen haben. Eine dieser Auswirkungen ist, dass Schwachstellen in einer RPC-Schnittstelle aufgedeckt werden.

Zusammenfassung

  • Ben Barnea, Forscher bei Akamai, fand zwei wichtige Schwachstellen in Microsoft Windows RPC- Services, die die Kennung CVE-2022-37998 und CVE-2022-37973 mit einem Basiswert von 7,7 erhalten haben.
  • Die Schwachstellen nutzen mehrere Fehler in der Local Session Manager RPC-Schnittstelle aus.
  • Die Schwachstellen führen zu Denial-of-Service-Angriffen, die die Funktion von Container- und Sitzungsservices (wie Microsoft Defender Application Guard, Sandbox, Docker und Windows Terminal Server) unterbinden.
  • Die Schwachstelle besteht in nicht gepatchten Windows 10-, Windows 11- und Windows Server 2022-Computern.
  • Die Schwachstellen wurden verantwortungsvoll an Microsoft weitergegeben und im Patch Tuesday für Oktober 2022 behoben.
  • Einen Proof of Concept der Schwachstellen haben wir in unserem Research Repositorygenannt.

Einführung

Die Akamai Security Intelligence Group hat sich im vergangenen Jahr intensiv mit der MS-RPC-Forschung beschäftigt. Obwohl das MS-RPC-Protokoll so viel leistet, ist es noch weitgehend unerforscht, und das kann reale Auswirkungen haben. Eine dieser Auswirkungen ist, dass Schwachstellen in einer RPC-Schnittstelle aufgedeckt werden. In diesem Blogbeitrag befassen wir uns mit den Schwachstellen in der RPC-Schnittstelle des Local Session Manager (LSM). 

LSM ist ein Service, der Teil des Session Manager-Subsystems ist. Es ist für die Verwaltung lokaler Sitzungen im Zusammenhang mit Terminalserver-Sitzungen auf einem Windows-Computer zuständig. Es kommuniziert mit anderen verwandten Windows-Komponenten, wie Winlogon und Csrss. 

LSM ist in lsm.dll implementiert und enthält sowohl Client- als auch Serverlogik. LSM stellt mehrere RPC-Schnittstellen zur Verfügung. Eine dieser Schnittstellen ist für die Verwaltung von Container-Sitzungen interessant, die innerhalb einer virtuellen Hyper-V-Maschine ausgeführt werden. Die Schwachstellen befinden sich in dieser Schnittstelle.

Um welche Schnittstelle handelt es sich?

Die neue RPC-Schnittstelle hat die UUID c938b419-5092-4385-8360-7cdc9625976a. Diese Schnittstelle verfügt über genau zwei Funktionen: ContainerCom_AskForSession und ContainerCom_SessionLoggedOff. Die Schnittstelle wird auch mit einem Sicherheitscallback registriert, das immer RPC_S_OK zurückgibt und somit den Zugang für alle ermöglicht. Der LSM-Server registriert einen Hyper-V-Socket (hvsocket)-Endpunkt, der nur für Hyper-V-Container zugänglich ist.

Abb. 1: Client baut RPC-Verbindung über hvsocket auf, während der Server einen hvsocket-Endpunkt einrichtet

Abb. 1: Client baut RPC-Verbindung über hvsocket auf, während der Server einen hvsocket-Endpunkt einrichtet

Wenn eine Sitzung innerhalb des Containers erstellt wird (z. B. aufgrund einer RDP-Verbindung), ruft der LSM-Client zunächst RpcGetRequestForWinlogon innerhalb der LSM des Containers auf. Diese Funktion verwaltet die Sitzungserstellung. Wenn diese innerhalb eines Containers ausgeführt wird, bittet sie zunächst um Genehmigung durch den Host. Dies geschieht durch den RPC-Aufruf ContainerCom_AskForSession an den Host unter Verwendung eines hvsocket zum übergeordneten System. Die RPC-Schnittstelle begrenzt die Anzahl der Sitzungen in den Containern. Dazu werden die neu erstellten Sitzungen verfolgt. 

Wie behält LSM den Überblick über die Sitzungen?

Die Antwort ist ganz einfach. Es gibt ein globales Objekt namens ContainerSessionServer, das zwei Variablen enthält, um die Sitzungen zu verfolgen:

  1. Anzahl der insgesamt erstellten Sitzungen. Dies ist auf eine Sitzung beschränkt, d. h. es ist jeweils nur eine Sitzung zulässig.
  2. Eine Zuordnung zwischen der GUID eines Containers und der Sitzungsanzahl des Containers. Dies ist auf zwei pro Container beschränkt.

Wenn ein Container eine Sitzung anfordert, prüft ContainerSessionServer::AskForSession zunächst, ob die Anzahl der Sitzungen kleiner als eins ist. Wenn dies der Fall ist, wird die Gesamtzahl der Sitzungen und damit auch der Sitzungszähler des Containers in der Map erhöht.

Wenn ContainerSessionServer::OnSessionLoggedOff aufgerufen wird (beim Beenden des Containers oder direkt als RPC-Aufruf), verringert die Funktion sowohl die Gesamtsitzungszahl als auch die Sitzungszahl des Containers um eins. 

RPC-Funktionen auf Schwachstellen überprüfen

Auch wenn diese Schnittstelle einfach und leicht zu implementieren ist, wurden vier Bugs gefunden, die wir zu zwei Schwachstellen verketten konnten.

Kette Nr. 1 – DoS durch einen kritischen Abschnitt – CVE-2022-37998

Bug Nr. 1 – Fehler beim Verlassen eines kritischen Abschnitts

ContainerSessionServer::AskForSession verwendet einen kritischen Abschnitt, um den Zugriff auf das globale Objekt ContainerSessionServer zu synchronisieren. 

Abb. 2: Dekompilierter Code der Schwachstelle. Die Funktion wird beendet, ohne den kritischen Abschnitt freizugeben

Abb. 2: Dekompilierter Code der Schwachstelle. Die Funktion wird beendet, ohne den kritischen Abschnitt freizugeben

Wie oben zu sehen ist, wird der kritische Abschnitt in Zeile 112 eingegeben. In den Zeilen 114 bis 116 wird anschließend geprüft, ob der Sitzungszähler des Containers das Limit erreicht hat (zwei). Ist dies der Fall, verfolgt LSM diese Sitzung nicht weiter und beendet die Funktion sofort (Zeile 125). Leider verlässt der Code den eingegebenen kritischen Abschnitt nicht. Deshalb müssen weitere Aufrufe dieser Schnittstelle darauf warten, dass dieser kritische Abschnitt freigegeben wird. 

Erinnern Sie sich aber nun daran, dass der gesamte Sitzungszähler auf eins begrenzt ist. Wie kann man also erreichen, dass der Sitzungszähler eines Containers zwei beträgt? Logisch gesehen ist das nicht möglich. Aber dann folgt der zweite Bug!

Bug Nr. 2 – Inkorrekte Erfassung des Zählers

Wird eine Sitzung in einem Container beendet, erfolgt ein RPC-Aufruf an ContainerSessionServer::OnSessionLoggedOff auf dem Host. Diese Funktion verringert zunächst den gesamten Sitzungszähler durch den Aufruf von DecreaseTotalSessionCount. Dies geschieht unabhängig von der Überwachung des Containers. Wird festgestellt, dass der Container nicht überwacht wird, wird das Programm ohne Erhöhung des Gesamtzählers der Sitzung beendet. 

Dies kann zu einem Gesamtsitzungszähler mit dem Wert einer negativen Zahl führen (da es sich um eine Ganzzahl mit Vorzeichen handelt). Man kann einfach viele OnSessionLoggedOff-Anfragen senden, bevor man eine AskForSession-Anfrage sendet. Dadurch wird der Gesamtsitzungszähler auf eine beliebige negative Zahl herabgesetzt. 

Verkettung des ersten und zweiten Bugs

Mit Bug Nr. 2 kann man den Zähler für die Gesamtzahl der Sitzungen ein paar Mal verringern, bis er eine negative Zahl erreicht hat. Anschließend kann Bug Nr. 1 ausgenutzt werden, indem zwei Anfragen an AskForSession gesendet werden. Beim zweiten Aufruf dieser Funktion wird geprüft, ob der Gesamtsitzungszähler kleiner als 1 ist, was aufgrund des zweiten Fehlers der Fall ist. Danach wird festgestellt, dass der Zähler der Containersitzung 2 beträgt. Daraufhin kehrt die Anwendung zurück, ohne den kritischen Abschnitt zu verlassen.

Abb. 3: Nutzungsprozess im Überblick

Abb. 3: Nutzungsprozess im Überblick

Der DoS hängt also von der Weiterleitung der neu eingehenden RPC-Aufrufe an denselben Thread ab, der den Deadlock im kritischen Abschnitt verursacht hat. Wenn die RPC-Laufzeit den neuen Aufruf an denselben Thread sendet, würde der DoS nicht auftreten, da EnterCriticalSection verschachtelte Besitzrechte zulässt, d. h. derselbe Thread kann EnterCriticalSection zweimal aufrufen. Wenn der RPC-Aufruf an einen anderen Thread als den, der den kritischen Abschnitt enthält, gesendet wird, geriete dieser in eine Warteschleife.

Kette Nr. 2 – DoS durch Speicherverlust – CVE-2022-37973

Bug Nr. 3 – Speicherverlust

ContainerSessionServer::AskForSession verfolgt auch Ereignisse von Containern wie das Beenden/Pausieren/Wiederaufnehmen von Containern. Dies geschieht durch den Aufruf von HcsOpenComputeSystem mit der GUID des Containers und die anschließende Registrierung eines Callbacks mit HcsRegisterComputeSystemCallback

Der registrierte Callback erhält ein Kontextobjekt. Der Kontext wird innerhalb von ContainerSessionServer::AskForSession zugewiesen. Leider wird die Funktion in vielen Fällen, in denen ein Fehler auftritt, beendet, ohne den für den Kontext zugewiesenen Speicher freizugeben. Dies führt zu einem Speicherverlust, den ein Angreifer mehrfach auslösen kann. Nach genügend Aufrufen ist der Speicher des LSM-Prozesses erschöpft und der Prozess stürzt ab. 

In unseren Tests führte das Senden von RPC-Anfragen in einer Endlosschleife zu einer Zuweisung von etwa 3 MB pro Sekunde. In unserem Fall stürzte der LSM-Service ab, nachdem 24 GB Speicher zugewiesen worden waren. Die Zeit, die benötigt wurde, um 24 GB zu verbrauchen, beträgt etwa zwei Stunden. Der Service wird nicht automatisch neu gestartet.

Bug Nr. 4 – Remotezugriff

Die Endpunkte in MS-RPC sind gemultiplext. Wenn ein Server mehrere Schnittstellen und mehrere Endpunkte registriert, ist jede Schnittstelle über jeden Endpunkt zugänglich. Endpunkte und Schnittstellen sind nicht aneinander gebunden.

Diese Schnittstelle soll nur über den hvsocket für Container zugänglich sein. In diesem Fall registriert LSM einen benannten Pipe-Endpunkt "\pipe\LSM_API_service", auf den remote zugegriffen werden kann. Aufgrund des Endpunkt-Multiplexing kann ein Angreifer eine Verbindung zum benannten Pipe-Endpunkt herstellen und eine Anfrage an die Schnittstelle des Containers senden. Das Problem ist einfach zu beheben – der Sicherheitscallback sollte prüfen, welchen Endpunkt der Client verwendet hat. Wenn es sich nicht um hvsocket handelt, sollte der Zugriff verweigert werden.

Verkettung des dritten und vierten Bugs

Die Tracker-Funktion des Containers basiert auf der Eigenschaft der Client-ID. Das bedeutet, dass bei einem hvsocket der Client-ID die GUID des Containers sein wird. Bei einer benannten Pipe ist dies der Computername des Clients.

Um den ersten Exploit auszulösen, muss der Client einen Client-ID haben, der eine aktuelle GUID eines laufenden Containers ist. Ein entfernter Client könnte diese Fehler also nur dann auslösen, wenn dieser erfolgreich die GUID eines laufenden Containers ermittelt und den Computernamen ändert – ein unwahrscheinliches Szenario.

Leider weist der dritte Fehler (Speicherverlust) die Objekte zu, bevor der angeforderte Container überprüft wurde. Das bedeutet, dass ein Remote-Angreifer (unter Verwendung von Bug Nr. 4) den Speicherverlust remote auslösen kann. Durch mehrfaches Aufrufen kann ein Angreifer den Speicher erschöpfen und damit stürzt der Prozess ab.

Auswirkungen

Diese Schwachstellen werden zwar als Denial-of-Service-Schwachstellen (DoS) eingestuft, haben aber dennoch Auswirkungen auf die Sicherheit. Diese ermöglichen einem Angreifer die Umgehung von Sicherheitsfunktionen.

Beim ersten Exploit (kritischer Abschnitt) gibt es einen DoS für die spezifische neue Schnittstelle. Dieses Problem würde die Erstellung neuer Sandbox-Instanzen verhindern.

Mit dem zweiten Exploit, der sowohl remote als auch von einem Container aus ausgelöst werden kann, stürzt der gesamte Prozess ab. Sämtliche Abhängigkeiten von LSM würden somit nicht funktionieren. Sicherheitsfunktionen wie Microsoft Defender Application Guard und Sandbox würden ebenfalls nicht funktionieren. Des Weiteren würden RDP und Docker auch nicht funktionieren.

Abb. 4: Darstellung des MDAG-Fehlers in Microsoft Edge

Abb. 4: Darstellung des MDAG-Fehlers in Microsoft Edge

Zusammenfassung

Diese Schwachstellen zeigen beispielhaft, wie etwas, das einfach oder unbedeutend erscheint, weitreichende negative Auswirkungen haben kann. Diese Schnittstelle mag unbedeutend erscheinen: Dabei sind einige Bugs aufgetreten, die leicht auszulösen sind und interessante Auswirkungen haben. 

In Wirklichkeit nutzen Cyberkriminelle diese Angriffsketten aus. Je unbedeutender etwas erscheint, desto eher wird es ignoriert. Diese Tatsache lässt sich bestens ausnutzen. 

Im Zusammenhang mit der fortlaufenden Arbeit, die wir im Bereich RPC leisten, ermutigen wir andere Forscher, nach ähnlichen Bugs in anderen RPC-Schnittstellen zu suchen.

Wenn Sie sich für RPC-Forschungsthemen wie dieses interessieren, finden Sie in unserem RPC-Toolkit weitere Beiträge und Tools. Folgen Sie uns auch auf Twitter, um Echtzeit-Updates zu dieser und anderen Forschungsarbeiten, die wir hier bei Akamai durchführen, zu erhalten.



Akamai Wave Blue

Verfasser

Ben Barnea

December 14, 2022

Akamai Wave Blue

Verfasser

Ben Barnea

Ben Barnea ist Sicherheitsforscher bei Akamai. Sein Fachgebiet ist die Durchführung von Sicherheits- und Schwachstellenforschung auf niedriger Ebene über verschiedene Architekturen hinweg, einschließlich Windows, Linux, Internet of Things und Mobilgeräten. Er lernt gerne, wie komplexe Mechanismen funktionieren und, was viel wichtigster ist, warum sie ausfallen.