Aufruf und Registrierung – Relay-Angriff auf WinReg RPC-Client
Zusammenfassung
Akamai-Forscher Stiv Kupchik hat eine neue Schwachstelle bezüglich der Erhöhung von Berechtigungen (Elevation of Privilege – EoP) im Remote Registry-Client von Microsoft gefunden: CVE-2024-43532, mit einem CVSS-Wert von 8,8.
Die Schwachstelle nutzt einen Fallback-Mechanismus in der WinReg-Client-Implementierung aus, der veraltete unsichere Transportprotokolle verwendet, wenn der SMB-Transport nicht verfügbar ist.
Über diese Schwachstelle können Angreifer die NTLM-Authentifizierungsdaten des Clients an die Active Directory Certificate Services (ADCS) weiterleiten und ein Nutzerzertifikat anfordern, das für die weitere Authentifizierung in der Domäne verwendet werden kann. Einen Proof of Concept haben wir in unserem GitHub-Repository geteilt.
Die Schwachstelle wurde dem Microsoft Security Resource Center im Februar 2024 umgehend gemeldet und als Teil des Patch Tuesday im Oktober 2024 gepatcht.
Die Schwachstelle betrifft alle ungepatchten Windows-Versionen.
Unsere Ergebnisse wurden auch auf der No Hat-Konferenz für Computersicherheit vorgestellt.
Einführung
MS-RPC ist die von Microsoft verwendete Implementierung des Remote Procedure Call (RPC)-Protokolls und -Standards. RPC ist eine Art prozessübergreifender Kommunikationsmechanismus, mit dem Prozesse Funktionen freigeben können, die von anderen Prozessen aufgerufen werden. Es handelt sich um eine Kernkomponente des Windows-Betriebssystems, auf die mehrere Dienste angewiesen sind – angefangen beim Service-Manager bis hin zu Abschaltungen in wininit.
Unser Team hat umfassende Untersuchungen zu MS-RPC durchgeführt, sowohl in Bezug auf Angriffe, wobei es uns gelungen ist, einen großen Angriffsvektor in Form von Caching-Angriffen zu identifizieren, als auch in Bezug auf Abwehrmaßnahmen und die hierfür erforderlichen Sicherheitsmechanismen.
Dieses Mal möchten wir RPC unter einem weiteren Gesichtspunkt betrachten. Jedes Protokoll, das die Kommunikation und Operationen zwischen verschiedenen Computern ermöglicht, muss in die Nutzerauthentifizierung involviert sein, und tatsächlich unterstützt das RPC-Protokoll die Weitergabe von Anmeldedaten und die Authentifizierung als Teil seines Bindungsprozesses. Sobald es jedoch zu einer Authentifizierung kommt, besteht auch ein Potential für Authentifizierungs-Relays, weswegen wir uns auf die Suche nach Relay-Möglichkeiten begeben haben.
RPC, Authentifizierung und was dazwischen liegt
RPC-Sitzungen werden von Bindungengehandhabt. Eine Clientanwendung stellt eine Verbindung zu einer Serveranwendung her, bindet sich an die erforderliche RPC-Schnittstelle und fragt die Ausführung einer bestimmten Funktion an (Abbildung 1).
Bind-Anforderung und -Antwort können je nach Verbindungserfordernis mehrere Datenfelder übertragen. Wenn keine Authentifizierung erforderlich ist, wird normalerweise die RPC-Bindung verwendet, um über die Transfersyntax zu entscheiden, die verwendet wird, um Funktionsparameter bei nachfolgenden Aufrufen einzukapseln.
Doch bei dieser Interaktion fehlt natürlich die Authentifizierung. Wie kann der Server die Identität des Clients erkennen und sicherstellen, dass dieser Client die angeforderte Aktion ausführen darf? Die Antwort lautet: Es ist unmöglich, sofern der Client keinen Sicherheitskontext (Authentifizierung) zur Bindung hinzugefügt hat. Standardmäßig sind RPC-Verbindungen nicht authentifiziert, und eine Authentifizierung ist in der Tat nicht für alle RPC-Server erforderlich.
Zur Authentifizierung (oder in RPC-Worten: um Sicherheitskontext hinzuzufügen) muss der Client der Binding-Anfrage zusätzliche Daten hinzufügen, das Authentifizierungsprotokoll aushandeln (z. B. NTLM oder Kerberos) und zusätzliche Metadaten einfügen, die für das Authentifizierungsprotokoll erforderlich sind (z. B. Nutzername, Domain usw.; siehe Abbildung 2).
Untersuchungsziele ermitteln
Die erste Priorität ist zu verstehen, wie die Authentifizierung aus API-Sicht aussehen sollte. Dies geschieht durch einen Aufruf an eine der RpcBindingSetAuthInfo* Funktionen durch den Client nach dem Erstellen eines Bindungshandles. In der Dokumentation dieser Funktionen findet sich ein Feld mit dem Namen AuthenticationLevel; dieses gibt die Sicherheitsstufe der Authentifizierung an.
Sicherheit durch Authentifizierung bedeutet mehr als lediglich zu prüfen, ob der Nutzer existiert und autorisiert ist. Sie dient auch dazu, Manipulationen zu verhindern. Die Authentifizierungsstufen reichen von der einfachen Überprüfung der erfolgreichen Verbindung (RPC_C_AUTHN_LEVEL_CONNECT) bis hin zur vollständigen Verschlüsselung und Signatur des gesamten Traffics, um sicherzustellen, dass nichts manipuliert wird (RPC_C_AUTHN_LEVEL_PKT_PRIVACY). Angreifer sind natürlich an einer möglichst einfachen Stufe ohne Schutz des Traffics interessiert, was gleichbedeutend damit wäre, dass der Traffic manipuliert werden kann.
Doch die Sache ist etwas komplexer. RPC-Relay-Angriffe sind kein neues Konzept. Daher wurden viele RPC-Clients und -Server in Windows bereits gepatcht, sodass die höchste Authentifizierungsstufe verwendet und damit sichergestellt wird, dass Relay-Angriffe nicht erfolgreich sind. Wir müssen das Betriebssystem durchforsten, um ältere Codebestandteile zu finden, die aus irgendeinem Grund noch unsicher sind (Abbildung 3).
WinReg – Ein verheißungsvoller Kandidat
Wie vermutet, umfasste die Liste der potenziellen Ziele, die wir gefunden haben, weniger als 5 % der gesamten RPC-Server und -Clients, da die meisten inzwischen keine unsichere Authentifizierung mehr verwenden. Aber wir haben einen verheißungsvollen Kandidaten gefunden: advapi32.dll.
advapi32.dll ist eine Kernkomponente der Windows-API und implementiert einen Großteil der „erweiterten“ Logik in Windows (wie der Name schon sagt). Sie exportiert mehr als 800 Funktionen aus verschiedenen Bereichen: Ereignisprotokollierung, Verschlüsselung, WMI und mehr.
Bei unserer Betrachtung haben wir festgestellt, dass gelegentlich die interne Funktion BaseBindToMachine einen Aufruf an RpcBindingSetAuthInfoA mit der Authentifizierungsstufe RPC_C_AUTHN_LEVEL_CONNECT sendet, was als Verhalten gewünscht ist. BaseBindToMachine wird von der exportierten (wenn auch nicht dokumentierten) Funktion RegConnectRegistryExW aufgerufen (Abbildung 4), wenn sie einen UNC-Pfad für einen Rechnernamen empfängt.
Bei der Betrachtung von BaseBindToMachinewird deutlich, dass darin tatsächlich Aufrufe an RpcBindingSetAuthInfoW und RpcBindingSetAuthInfoAenthalten sind. Ersterer wird sicher mit der Authentifizierungsstufe RPC_C_AUTHN_LEVEL_PKT_PRIVACY verwendet, während letzterer die Authentifizierungsstufe RPC_C_AUTHN_LEVEL_CONNECT nutzt, die weitergeleitet werden kann, da sie die Authentizität oder Integrität der Verbindung nicht überprüft (Abbildung 5).
Wir müssen lediglich herausfinden, warum es zwei widersprüchliche Aufrufe gibt. Ein Blick auf die Funktionslogik macht deutlich, dass diese über eine Funktionszeigervariable und eine Reihe von Funktionen verfügt (Abbildung 6). Diese Funktionen legen die RPC-Bindungsinformationen so fest, dass sie einen bestimmten RPC-Transport verwenden. Dabei wird standardmäßig versucht, SMB und benannte Pipes zu verwenden. Wenn dies jedoch fehlschlägt, wird versucht die Bindung über SPX, TCP/IP und andere herzustellen.
Aus irgendeinem Grund wird nach der Zurücksetzung auf ein von SMB abweichendes Protokoll RpcBindingSetAuthInfoA verwendet, um als Authentifizierungsstufe „Connect“ festzulegen, was unsicher ist.
Zurücksetzen auf TCP/IP ist vielversprechend, da dies bedeutet, dass die unsichere Authentifizierungsmethode verwendet werden kann, um den Traffic mithilfe eines MITM-Angriffs (Machine in the Middle) weiterzuleiten, ohne dass der Client dies bemerkt. Dies ist auch bei den anderen Transportprotokollen möglich, diese sind jedoch ziemlich veraltet, sodass deren Verwendung in einem modernen Netzwerk eher unrealistisch ist (und durch deren Verwendung Alarm ausgelöst werden könnte). TCP/IP ist viel gebräuchlicher als ein RPC-Transport und sollte daher auch in einer Red Team-Einstellung ok sein.
Wichtig zu wissen ist, dass sowohl BaseBindToMachine als auch RegConnectRegistryExW eine Kennzeichnung als Argument akzeptieren, das das Fallback-Verhalten verhindert, aber die Basisfunktion RegConnectRegistryW ruft RegConnectRegistryExW auf, ohne dass diese Kennzeichnung vorhanden ist.
Der Relay-Prozess
Das Weiterleiten (relay) ist recht einfach, da NTLM-Weiterleitung eine gängige Technik ist. Die benötigte Logik ist bereits größtenteils in ntlmrelayx von Impacket implementiert, was am häufigsten verwendet wird.
Erstellen des RPC-Relay-Servers
ntlmrelayx fehlt ein TCP/IP RPC-Server, da es lediglich einen SMB-Server implementiert. Daher muss ein eigener Relay-Server erstellt werden, der die benannte winreg-Pipe ablehnt, um einen Fallback zur TCP/IP-Bindungsfunktion auszulösen.
Es gibt drei kritische Punkte, die implementiert werden müssen:
den RPC-Endpunkt-Mapper
die RPC-Bindungsanforderung mit NTLM
die NTLM-Sicherheitsfrage
Der RPC-Endpunkt-Mapper ist für die Übersetzung der RPC-Schnittstellen-UUIDs in ihre jeweiligen Endpunkte verantwortlich. Im Falle eines TCP/IP-Transports wäre dies eine Portnummer. Im Gegensatz zu SMB, bei deren Endpunkten es sich um benannte Pipes handelt, die eindeutig und im Voraus bekannt sind, verwenden die TCP-Endpunkte flüchtige Ports, sodass eine weitere Übersetzungsebene erforderlich ist.
Entscheidend sind die NTLM-bezogenen Probleme. Bei der RPC-Bindung mit NTLM wird bei der Bindungsanforderung eine NTLM-Aushandlungsnachricht und anschließend mit der Bindungsantwort eine NTLM-Sicherheitsfrage gesendet. Schließlich muss der Client eine weitere Nachricht namens AUTH3 mit der Sicherheitsantwort senden (Abbildung 7).
Zur Weiterleitung müssen lediglich die jeweiligen Nachrichten auf dem RPC-Server analysiert werden. Sobald eine NTLM-Aushandlungsnachricht in einer Bindungsnachricht zu sehen ist, wird unsere eigene Verbindung zu unserem Ziel-Authentifizierungsserver geöffnet und ebenfalls eine Authentifizierung über NTLM angefordert. Dann müssen wir nur die Sicherheitsfrage erfassen, die der Server an uns sendet, diese an das Opfer weiterleiten und die Antwort an den Server zurückleiten, um eine eigene authentifizierte Sitzung zu erhalten.
Wir müssen nur überlegen, an welchen Server die Authentifizierung weitergeleitet werden soll.
RPC-zu-RPC-Weiterleitung
Am Naheliegendsten scheint die Weiterleitung an einen anderen RPC-Server auf einem anderen Computer, z. B. den Servicemanager oder den Taskplaner, um auf diese Weise eine Remote-Code-Ausführung zu erreichen. Dabei erweist sich jedoch als Problem, dass die unsichere Authentifizierung über RPC nicht mehr verwendet wird, sodass eine Weiterleitung an einen hochkarätigen RPC-Server nicht möglich ist. (Wegen dieses Mangels an unsicherer Authentifizierung über RPC haben wir auch unsere Untersuchungsziele begrenzt.)
Sowohl für Servicemanager- als auch für Taskplaner-RPC-Server ist RPC_C_AUTHN_LEVEL_PKT_PRIVACY erforderlich, das den gesamten Traffic mit dem NTLMv2-Hash des Clients verschlüsselt, der selbst bei einer Weiterleitung unbekannt ist. Stattdessen muss eine andere Perspektive berücksichtigt werden.
RPC an ADCS
Das Team von SpecterOps hat gründlich an ADCS gearbeitet, insbesondere an der NTLM-Weiterleitung an ADCS. Dies ist auch standardmäßig in Impacket implementiert, sodass es lediglich erforderlich ist, die authentifizierte Sitzung an das Modul HTTPAttack von Impacket weiterzuleiten. Alles weitere geschieht dann automatisch.
Der HTTP-Webserver von ADCS ist ungeschützt und anfällig für Relay-Angriffe. Wenn wir dies ausnutzen, können wir nach der Authentifizierung ein Nutzerzertifikat anfragen, das wir dann selbst für die Authentifizierung verwenden können, ohne dass wir die Authentifizierung erneut übermitteln müssen (Abbildung 8).
Dieses Zertifikat wurde verwendet, um sich beim LDAP-Service auf dem Domaincontroller zu authentifizieren und einen dauerhaften neuen Domainadministrator in der kompromittierten Domain zu erstellen (Abbildung 9).
Potenzielle Auswirkungen
Eine Funktion in advapi ist an sich nicht interessant, sie ist nur dann folgenreich, wenn sie von etwas anderem verwendet wird. Eine schnelle Suche nach Importen von RegConnectRegistryExW oder RegConnectRegistryExA zeigt auf einem aktuellen Domänencontroller nichts an, aber eine Suche nach RegConnectRegistryW deckt viele potenzielle Kandidaten wie certutil und certsrv (AD CS), EFS, DFS und mehr auf.
Erkennung
Der Remote Registry-Service ist nicht standardmäßig auf allen Windows-Computern aktiviert. Dessen Status lässt sich mithilfe der folgenden osquery erkennen:
SELECT display_name, status, start_type, pid FROM services WHERE name='RemoteRegistry'
Dies schützt jedoch nicht vor CVE-2024-43532, da es sich um ein Client-Problem handelt. Die Abfrage sollte echte Remote Registry-Anwendungsfälle in der Organisation ergeben, die Sie bei der Absicherung Ihrer Systeme möglicherweise berücksichtigen müssen.
Zum Erkennen von Clients, die die anfälligen WinAPIs verwenden, können Sie die folgende YARA-Regel verwenden:
import "pe"
rule winreg_client_import {
meta:
description = "Detect binaries that rely on RegConnectRegistry"
author = "Stiv Kupchik with Akamai Technologies"
condition:
pe.is_pe and (
pe.imports(pe.IMPORT_ANY, "advapi32.dll", "RegConnectRegistryA")
or pe.imports(pe.IMPORT_ANY, "advapi32.dll", "RegConnectRegistryW")
or pe.imports(pe.IMPORT_ANY, "advapi32.dll", "RegConnectRegistryExA")
or pe.imports(pe.IMPORT_ANY, "advapi32.dll", "RegConnectRegistryExW")
)
}
Nutzer von Akamai Guardicore Segmentation können auch Richtlinien für den Traffic erstellen, der in den RemoteRegistry-Service eingeht (Abbildung 10).
Es ist auch möglich, die Ereignisverfolgung von Windows (Event Tracing for Windows – ETW) zu verwenden, um den RPC-Traffic sowohl auf Client- als auch auf Server-Seite der Kommunikation zu überwachen. Wir haben dieses Thema im Rahmen unserer Präsentation bei der Black Hat 2023 und dem Blogbeitrag dazu erläutert. Nutzer können unser Open-Source-Tool für RPC-Sichtbarkeit verwenden, um RPC-Aufrufe zu verfolgen und nach der WinReg RPC-Schnittstellen-UUID {338cd001-2244-31f1-aaaa-900038001003}zu filtern.
Fazit
Obwohl das RPC-Protokoll – und MS-RPC – im Hinblick auf Sicherheit entwickelt wurden, lässt sich die Entwicklung der Sicherheitsprinzipien im Laufe der Zeit durch die Analyse verschiedener RPC-Schnittstellenimplementierungen deutlich erkennen. Während die meisten RPC-Server und -Clients heutzutage sicher sind, lassen sich zuweilen Überreste unsicherer Implementierungen unterschiedlichen Ausmaßes finden.
In diesem Fall ist es gelungen, eine NTLM-Weiterleitung zu erreichen, Angriffsklasse, die eigentlich der Vergangenheit angehören sollte. Dies belegt, dass die Netzwerksicherheit so gründlich wie möglich konzipiert sein muss, da man nie wissen kann, welche veralteten Schnittstellen noch geöffnet sind oder ausgeführt werden.
Chronik der Veröffentlichung
01.02.2024 – Schwachstelle an MSRC gemeldet
25.04.2024 – Bericht als Dokumentationsproblem abgeschlossen
17.06.2024 –Bericht mit besserer PoC und Erläuterung erneut geöffnet
08.07.2024 – Schwachstelle bestätigt
08.10.2024 – Schwachstelle gepatcht
19.10.2024 – Blogbeitrag veröffentlicht