A compromised host where someone has run az, Azure PowerShell, or an Azure SDK usually holds cached access and refresh tokens. A refresh token is the prize: it mints fresh access tokens for any resource the user consented to, long after the session, and often survives a password reset.
Where the tokens live#
# az cli
~/.azure/msal_token_cache.json # MSAL cache: access + refresh tokens
~/.azure/azureProfile.json # subscriptions, tenant, signed-in identity
# legacy
~/.azure/accessTokens.json
# Azure PowerShell
~/.Azure/AzureRmContext.json
Using what you find#
# a live az session: mint a token for any audience
az account get-access-token --resource https://graph.microsoft.com/ --query accessToken -o tsv
az account get-access-token --resource https://management.azure.com/ --query accessToken -o tsv
A recovered refresh token is replayed with ROADtools or TokenTactics to request access tokens for arbitrary first-party client IDs and audiences, including ones the victim never used interactively (FOCI family refresh tokens).
Exploitation notes#
- Prefer the refresh token over an access token: access tokens expire in about an hour, refresh tokens last days to months and re-mint freely.
- FOCI ("family of client IDs") refresh tokens work across many Microsoft first-party clients, so one refresh token pivots between Graph, ARM, and Office endpoints.
- Tokens are bearer credentials with no device binding unless CAE or token-protection is enforced, so they move to the attacker's host cleanly.
Tools#
- ROADtools (
roadrecon,roadtx): import and exchange refresh tokens across clients. - TokenTactics: request tokens for different resources from a refresh token.
- az cli (
account get-access-token) on a live session.