AuthCodeFix aka ConsentFix

Net voor de jaarwisseling duikt ConsentFix op: een slimme OAuth-aanval die legitieme authenticatieflows misbruikt om de authorization code te stelen en aanvallers daarmee de sleutels tot Microsoft Entra in handen geeft. We leggen uit waarom dit ondanks Conditional Access werkt, welke signalen het in de logs achterlaat en hoe defenders het kunnen detecteren en stoppen voordat er echte schade ontstaat.

AuthCodeFix aka ConsentFix

Zoals de traditie het wil, verschijnt er net voor het einde van het jaar een nieuwe kwetsbaarheid of een slim aanvalspad, en mogen defenders opnieuw proberen hun gebruikers te beschermen. Andere aanvallers en red teamers kijken intussen aandachtig mee en passen zich aan.

Dit jaar detecteerde PushSecurity een aanval die ze "ConsentFix" noemden, een evolutie van de ClickFix-aanval die erop leunt dat de gebruiker de aanvaller een URI aanreikt waarmee die in feite de sleutel tot het Entra-koninkrijk overhandigt. De methode die in het wild werd gebruikt, had een handmatige copy-and-paste-actie van de gebruiker nodig om te werken. Binnen een paar dagen publiceerde John Hammond een video met een verbeterde versie van de aanval waarvoor geen copy and paste meer nodig was: de gebruiker kon zijn auth code simpelweg naar de aanvaller slepen.

Wanneer we in de technische details duiken van waarom deze aanval werkt en device compliance en andere Conditional Access-vereisten schijnbaar omzeilt, komen we terecht bij de OAuth 2.0 authorization code flow.

OAuth 2.0 authorization code flow

De aanvaller maakt een Microsoft Entra login-URI die de client "Microsoft Azure CLI" en de resource "Azure Resource Manager" aanspreekt, en opent deze URI wanneer de gebruiker de kwaadaardige website bezoekt.

Gemapt op de authorization code flow komt dit overeen met de eerste stap die een native public app zoals de Azure CLI normaal zou aanroepen om de gebruiker te authenticeren. De applicatie start op de machine waarop ze wordt uitgevoerd een listener op een willekeurige hoge poort. Die poort wordt gebruikt als zogenoemde reply URI.

Je kunt dit eenvoudig zelf reproduceren, bijvoorbeeld met TokenTacticsV2, of door de URI handmatig samen te stellen.

TokenTacticsV2

Nadat de gebruiker zich succesvol bij Entra ID heeft aangemeld, wordt hij doorgestuurd naar de reply URI, bijvoorbeeld http://localhost:3001. In een normaal scenario zou de Azure CLI de aanroep naar deze URI nu accepteren en de belangrijke, kritieke informatie ontvangen die deel uitmaakt van de redirect:

  • code
    Dit is de authorization_code, die de applicatie gebruikt om een bearer token op te vragen, bestaande uit een access token, een ID token en optioneel het refresh token.
    Volgens de documentatie is deze code ongeveer 10 minuten geldig en moet hij binnen die tijd worden ingewisseld.
  • state
    Dit is een optionele parameter en de applicatie hoort te controleren of die in request en response identiek is.

In het aanvalsscenario wordt de gebruiker ook doorgestuurd, maar omdat er geen applicatie op localhost draait, loopt de browser tegen een foutmelding aan.

De browser loopt tegen een foutmelding aan

Maar de URI bevat nog steeds de gevoelige informatie, en dat is precies wat de aanvaller de gebruiker wil laten aanleveren. Als de gebruiker daaraan toegeeft, wisselt de aanvaller het tokenmateriaal in en kan hij vervolgens met het access token en het refresh token bij de resource, in dit geval Azure Resource Manager.

Op deze screenshot zie je hoe je het bearer token ophaalt met de URI die de gebruiker heeft aangeleverd.

Bearer token met de door de gebruiker aangeleverde URI

Als je je detecties wilt testen, voer de laatste stap dan uit vanaf een ander systeem, in een ander netwerk.

Detectie-artefacten

Als je de aanval reproduceert en de SigninLogs en AADNonInteractiveUserSignInLogs bekijkt, zie je twee events voor deze ene sign-in-activiteit. Het eerste event is de daadwerkelijke aanmelding van de gebruiker, het tweede komt van de infrastructuur van de aanvaller.

Activity Log

Het grote verschil is dat het eerste event een interactief sign-in-event is en het tweede een non-interactive event. Dat komt overeen met de twee fasen van de authenticatieflow: eerst de gebruiker, dan de applicatie of in ons geval de aanvaller.

Normaal gedrag van de Azure CLI zou zijn dat beide sign-in-events van hetzelfde IP-adres komen. In ons geval verschillen de IP-adressen echter, en ze komen uit verschillende landen. Dat laatste is natuurlijk geen betrouwbare indicator, want de aanvaller kan zich in hetzelfde land als het slachtoffer bevinden om zijn sporen te verbergen.

Op zoek naar een goede manier om die twee events aan elkaar te koppelen, was het eerste idee de Unique Token Identifier (UTI) te gebruiken. Microsoft gebruikt echter verschillende waarden voor de UTI van de authorization code en die van het bearer token, waardoor deze aanpak niet werkt als betrouwbare koppeling.

Unique Token Identifier

De SessionId is wel een goede koppeling tussen beide, al gaat het om een langlopend ID dat meerdere van deze eventcombinaties kan bevatten, ook legitieme.

Met de aanvullende kennis over de beperkingen van de auth code flow en met het user id en het application id als extra koppeling kun je tijd als belangrijke detectiefactor inzetten:

  • Beide events hebben dezelfde SessionId
  • Beide events hebben dezelfde ApplicationId
  • Beide events hebben dezelfde UserId
  • Het tweede event moet na het eerste event komen
  • Het tweede event moet binnen ongeveer een tijdvenster van 10 minuten na het eerste event vallen. Gebruik niet exact 10 minuten, want Microsoft schrijft "[...] they expire after about 10 minutes"
  • Beschouw alleen het eerstvolgende tweede event, niet de daaropvolgende

Fun fact
De ResourceIdentity is geen goede koppeling, omdat de aanvaller de resource kan wijzigen: die is niet aan de auth code gebonden. Het aangesproken application ID kan niet worden gewijzigd.

Ruis verminderen

Deze kennis leverde ons al een goed werkende detectie op, maar er zaten ook benign positives tussen. Moderne developers gebruiken cloudresources die zich voordoen als lokale instances, wat in de logs tot onregelmatige loginpatronen leidt.

Het cruciale verschil zit in de tijdcomponent. Waar de aanval gebruikersinteractie vereist om de URI te kopiëren en te plakken of te slepen, is de GitHub Codespace-use case die we als bron van de benign positives identificeerden volledig geautomatiseerd en wisselt hij de auth code binnen enkele seconden in.

Alles wat deze authenticatiedans binnen een paar seconden afwikkelt, kun je dus met grote waarschijnlijkheid als benign wegfilteren.

Een andere bron van ruis kunnen wisselende egress points voor je internetverkeer zijn, met name in SD-WAN-, ZTNA- of Secure Web Gateway-scenario's.

Getroffen first-party applicaties

Terwijl het oorspronkelijke rapport "Microsoft Azure CLI" als misbruikte applicatie noemt, zijn er veel verschillende Microsoft first-party apps met pre-consent in elke tenant die localhost als redirect aanbieden. En niet alleen die zijn een doelwit. De aanvaller kan ook reply-, test- en dev-URL's misbruiken die niet publiek resolvable zijn.

Hier is een lijst van de meest opvallende applicaties die daarnaast uitgebreide pre-consented permissions op resources hebben.

  • Microsoft Azure CLI (04b07795-8ddb-461a-bbee-02f9e1bf7b46)
  • Microsoft Azure PowerShell (1950a258-227b-4e31-a9cf-717495945fc2)
  • Visual Studio (04f0c124-f2bc-4f59-8241-bf6df9866bbd)
  • Visual Studio Code (aebc6443-996d-45c2-90f0-388ff96faa56)
  • MS Teams PowerShell Cmdlets (12128f48-ec9e-42f0-b203-ea49fb6af367)

Een volledige lijst van deze apps staat inmiddels in EntraScopes.com van onze collega Fabian Bader.

Mitigaties en bescherming

Beperk het aanvalsoppervlak en de doelgroep

Implementatie-inspanning: Laag tot hoog (afhankelijk van de inspanning om legitieme gebruikers te identificeren)
Mitigatie: Gemiddeld (verkleint de potentiële doelgroep voor de aanval)
Scope: beperkt

Optie 1: User Assignment vereisen

Voorwaarden:

  • Voeg de service principal voor de getroffen first-party apps toe via de Microsoft Graph API of PowerShell
  • Zet de user assignment requirement op het service principal-object met de Microsoft Graph API of PowerShell
  • Richt een proces in om gebruikers op aanvraag toe te wijzen via Access Packages, PIM-for-Groups (voor just-in-time toegang) of een combinatie van beide.

// Example for Microsoft Graph PowerShell
Connect-MgGraph -Identity
$AppId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46" // Microsoft Azure CLI
$sp = Get-MgServicePrincipal -Filter "appId eq '$AppId'"
Update-MgServicePrincipal -ServicePrincipalId $sp.Id -AppRoleAssignmentRequired:$false

Voordeel:

  • Maakt het beheer van user assignments via Access Packages of handmatig groepslidmaatschap mogelijk om de blootstelling aan deze aanvalstechniek te beperken.
  • Mogelijkheid tot just-in-time toegang in combinatie met een eligible group membership, waarmee tijdelijke toegang tot CLI-tools ontstaat en het aanvalsoppervlak verder krimpt.
  • Wordt toegepast voordat Conditional Access-policies worden geëvalueerd.
  • Beperkt ook het aanvalsoppervlak voor andere scenario's.

Nadeel:

  • Kan alleen op specifieke gebruikers worden gescoped en niet worden gecombineerd met andere eisen, zoals het gebruik van specifieke devices
  • Alle legitieme gebruikers van CLI-tools moeten worden geïdentificeerd
  • Neveneffecten en organisatorische impact moeten zorgvuldig worden beoordeeld door eerdere sign-ins te bekijken.

Optie 2: Toegang blokkeren met Conditional Access-policies

Voorwaarden:

  • Maak een Conditional Access-policy die toegang tot CLI-tools blokkeert, met uitzondering van legitieme gebruikers, door "Microsoft Graph Command Line Tools" en "Windows Azure Service Management API" te targeten
  • Beheer uitzonderingen via groepslidmaatschap, handmatig of via entitlement management (bijvoorbeeld Access Packages).

Voordeel:

  • Voorkomt tokenuitgifte voor niet-legitieme of niet-geprivilegieerde gebruikers.
  • Maakt granulaire scoping mogelijk op basis van aanvullende condities zoals device of netwerk.

Nadeel:

  • Alle legitieme gebruikers van CLI-tools moeten worden geïdentificeerd en uitgesloten.
  • Neveneffecten en organisatorische impact moeten zorgvuldig worden beoordeeld door eerdere sign-ins te bekijken en de policy in report-only-modus te evalueren.

Tokenuitgifte via de authorization code flow blokkeren

Optie: Token Protection vereisen
Implementatie-inspanning: Hoog
Mitigatie: Hoog
Scope: Zeer beperkt

Voorwaarden:

  • Microsoft Entra ID P1-licenties
  • Entra ID Registered Devices, Hybrid of Entra ID-joined devices op het Windows-platform
  • Web Account Manager (WAM) inschakelen in Azure CLI, Azure PowerShell en Microsoft Graph PowerShell (standaard in de nieuwste versies)
  • Conditional Access configureren met targeting op:
    • Cloud App targeting op de volgende apps:
      • Office 365 Exchange Online
      • Office 365 SharePoint Online
      • Microsoft Teams Services
    • Client apps onder Mobile apps and desktop clients om Token Protection te vereisen.
    • Selecteer Windows als device platform voor de targeting van de policy

Voordeel:

De token protection van Microsoft Entra vereist proof‑of‑possession (PoP), wat alleen kan worden afgedwongen wanneer de client direct communiceert met een vertrouwde token broker zoals de Web Account Manager (WAM) op Windows. Omdat browsers dat beveiligde kanaal niet kunnen opzetten, wordt de authorization code flow die in een browser wordt gestart, geblokkeerd onder token protection-policies.

Wanneer de policy token protection afdwingt die broker‑managed PoP vereist, kan de authorization code die aan een browser wordt teruggegeven niet worden ingewisseld, omdat de browser tijdens de uitwisseling van code naar token niet het vereiste broker‑signed bewijs kan leveren

In dat geval worden aanvallen met AuthCodeFix volledig gemitigeerd, zolang de applicatie door Token Protection beschermd kan worden.

Zoals de screenshot hieronder laat zien, verhindert Token Protection succesvol het inwisselen van de authorization code flow die het slachtoffer via een phishingactie heeft gestart.

Token Protection verhindert succesvol het inwisselen van de authorization code flow

Nadeel:

  • Alleen de volgende resources worden officieel ondersteund:
    • Office 365 Exchange Online
    • Office 365 SharePoint Online
    • Microsoft Teams Services

      De Microsoft Graph API wordt indirect gedekt door de eerder genoemde resources en Microsoft Graph PowerShell staat vermeld als ondersteunde client. In onze tests hebben we kunnen verifiëren dat de aanval in dit scenario wordt gemitigeerd. "Windows Azure Service Management API" staat niet vermeld als ondersteunde resource. Beide CLI-clients (Azure CLI en Azure PowerShell) ondersteunen WAM, wat een client-side voorwaarde is voor het gebruik van Token Protection. Microsoft heeft in een blogpost aangekondigd de token protection-mogelijkheden uit te breiden naar Azure-managementscenario's.
  • Sommige bugs in Microsoft Graph PowerShell dwingen je de WAM-integratie tijdelijk uit te schakelen
  • Neveneffecten en organisatorische impact moeten zorgvuldig worden beoordeeld door eerdere sign-ins te bekijken en de policy in report-only-modus te evalueren. De cloud app targeting raakt ook de productiviteitstoegang tot Microsoft 365.
  • Beperkte scope door de beschikbaarheid op ondersteunde platformen en Entra ID-geïntegreerde devices.

Verdere tokenuitgifte blokkeren via een compliant network check of trusted network

Implementatie-inspanning: Gemiddeld
Mitigatie: Gemiddeld
Scope: Breed

Optie: Toegang buiten het Compliant network blokkeren met Global Secure Access

Voorwaarde:

  • Entra ID P1-licentie
  • Entra ID Registered Devices, Hybrid of Entra ID-joined devices op de platformen Windows, macOS, Android en iOS
  • Global Secure Access Client op alle betrokken clients en geactiveerde Entra Internet Access voor het M365 Traffic Profile
  • De Conditional Access-policy die de network compliant check afdwingt, moet op alle cloud apps worden toegepast

Voordeel:

Blokkeer aanvullende tokenuitgifte door een trusted network check af te dwingen. Deze mitigatie zorgt ervoor dat aanvallers geen nieuwe tokens kunnen verkrijgen met het refresh token uit de authorization code flow. Het voorkomt echter niet het initiële inwisselen van de authorization code of de uitgifte van het eerste access token, dat buiten het compliant network geldig blijft omdat het oorspronkelijk door het slachtoffer is aangevraagd.

Het afdwingen van GSA met de Compliant Network-conditie blokkeert ook andere Token Replay-scenario's en levert extra logs op die zeer nuttig kunnen zijn voor detecties en hunting.

Nadeel:

  • Alleen van toepassing op gebruikers en devices met een uitgerolde Global Secure Access-client
  • Beperkte scope door de beschikbaarheid op Entra ID-geïntegreerde devices
  • Het afdwingen van Compliant Networks via CA vereist enkele uitzonderingen, bijvoorbeeld voor Intune, om kip-en-eiproblemen te voorkomen. Grondig testen is nodig voordat je uitrolt

Hunting queries

Zodra aan alle voorwaarden voor de mitigatie van tokendiefstal is voldaan, zoals de uitrol van de GSA-client (inclusief ingestion van NetworkAccessTraffic-logs) en het benutten van WAM-authenticatie, krijgen we extra mogelijkheden voor threat hunting en verificatie.

GSA-logs en WAM-authenticatie inzetten voor hunting of om vertrouwen in detectieresultaten te verifiëren

Deze hunting query maakt gebruik van NetworkAccessTraffic-logs uit Global Secure Access (GSA), die het initiërende proces voor de communicatie met het Microsoft Entra token endpoint bevatten. Daarmee kun je vaststellen of een tokenaanvraag direct uit een browser kwam en of er aanvullende tokenaanvragen buiten het GSA-netwerk zijn gedaan.

Deze query werkt en levert alleen betrouwbare resultaten wanneer aan de voorwaarden is voldaan; anders leidt hij tot een hoog aantal false positives.

Waarom dit uitmaakt: Bij het aanmelden via CLI- of PowerShell-modules met Web Account Manager (WAM) op Windows-devices komt er geen browser-based authorization code aan te pas. Dit aanmeldgedrag is standaard in de nieuwste versie. Als het initiërende proces dus een browser-executable is (bijvoorbeeld msedge.exe), is dat een sterke indicator voor verdachte activiteit. Op macOS wordt het proces gestart door de Company Portal-app (com.microsoft.CompanyPortalMac.ssoextension) wanneer Platform SSO wordt gebruikt.

Token Binding en PoP: WAM-authenticatie bindt tokens doorgaans aan het device door Proof-of-Possession (PoP) af te dwingen. Aanvallers kunnen zonder PoP geen verdere gebonden tokens uitgeven, dus een ongebonden refresh token is een andere sterke indicator.

Beperkingen: Alle genoemde signalen zijn alleen beschikbaar wanneer het device dat toegang zoekt, geregistreerd is bij of joined is aan Microsoft Entra ID.

Logica van de confidence score: De query combineert meerdere signalen om een confidence score te berekenen:

  • Aanwezigheid van een browserproces dat tokenaanvragen initieert.
  • Detectie van en downgrade naar ongebonden tokens.
  • Wijzigingen van network provider (inclusief van compliant naar non-compliant) tussen sign-ins.

Deze signalen kun je in de query gebruiken om naar activiteit te hunten of om bij een incident een confidence score af te leiden op basis van de eerdere detectie.

Signalen voor de hunting query

Afhankelijk van de condities wordt de volgende score weergegeven:

Een zeer hoge confidence score wordt weergegeven wanneer NetworkAccessTraffic-logs een bekend browserproces aangeven in plaats van een geïnitieerde tokenaanvraag, en er een downgrade van een ongebonden token is gedetecteerd.

Een hoge confidence score wordt weergegeven wanneer de aanmelding vanaf een andere Network Provider (ASN) en vanuit een non-compliant netwerk komt waarbij ongebonden tokens betrokken zijn.

Een gemiddelde confidence score wordt weergegeven wanneer alleen een wijziging van Network Provider en een compliant netwerk wordt vastgesteld, samen met een wijziging van het gebruikte tokentype.

De nieuwste versie van de hunting query vind je op GitHub.

Hunten naar activiteiten met uitgegeven tokens

Je doet er goed aan je onderzoek verder uit te breiden dan sign-in-events, naar activiteiten die zijn uitgevoerd met tokens die de aanvaller heeft uitgegeven. Onze collega Thomas Naunheim heeft een KQL-functie gepubliceerd met de naam MicrosoftCloudActivity, die bij dit uitgebreide hunten kan helpen. Daarnaast kan de betrokken SessionId worden gecorreleerd met verdachte UniqueId-waarden uit eerdere hunts, voor een diepere analyse.

KQL-functie

In dit voorbeeld gebruikte de aanvaller het tijdens de aanval verkregen refresh token om een access token voor de Microsoft Graph API uit te geven. Dat token werd vervolgens gebruikt om persistente toegang en lateral movement te behouden, door een client secret toe te voegen aan een applicatie die eigendom is van het slachtoffer. De query levert details over de Graph API-operatie, inclusief de token protection-status en of de operatie buiten het Global Secure Access-netwerk plaatsvond.

Screenshot van de Graph API-operatie

Verder lezen

Vergelijkbare berichten