Disclaimer: All research and opinions expressed here are my own and are independent of any employer or organisation.

Potential Token Replay from Different ASNs

hunt-2025-034 v1.0 Entra created Paul Newton

Hypothesis

Threat Actors will use token theft as a means of initial access, privilege escalation and persistence. Poorly secured tokens by third parties can increase the risk of token theft and replay.

Potential Token Replay from Different ASNs

This analytic looks for cases where we see two different ASNs for the initial authentication to an app in Entra, and then a second and different ASN, for the same token, in GraphAPI logs. This could be indicative of token replay. There’s also an exclusion list to bin off noise from Microsoft, any any other ranges you’re not interested in.

KQL
let ExcludedGraphASNs = dynamic([8075]);
let CIDRASN = (externaldata (CIDR:string, CIDRASN:int, CIDRASNName:string)
['https://firewalliplists.gypthecat.com/lists/kusto/kusto-cidr-asn.csv.zip']
with (ignoreFirstRecord=true));
let GraphLogs =
MicrosoftGraphActivityLogs
| evaluate ipv4_lookup(CIDRASN, IPAddress, CIDR, return_unmatched=true)
| extend GraphASN = CIDRASN
| extend GraphASNName = CIDRASNName
| project SignInActivityId, GraphIPAddress = IPAddress, GraphASN, GraphASNName,
        Location, ResponseStatusCode, UserAgent, RequestMethod, RequestUri, TimeGenerated;
let AADLogs =
AADNonInteractiveUserSignInLogs
| extend TokenDetails = parse_json(TokenProtectionStatusDetails)
| extend signInSessionStatus = tostring(TokenDetails.signInSessionStatus)
| project UniqueTokenIdentifier, AADIPAddress = IPAddress,
        AADLocation = Location, AADASN = AutonomousSystemNumber,
        DeviceName = tostring(parse_json(DeviceDetail).displayName),
        signInSessionStatus, Identity, AppDisplayName;
GraphLogs
| join kind=inner (AADLogs) on $left.SignInActivityId == $right.UniqueTokenIdentifier
| where isnotempty(GraphASN) and isnotempty(AADASN)
| where GraphASN != AADASN
| where GraphASN !in (ExcludedGraphASNs)
| project TimeGenerated, SignInActivityId, Identity, AppDisplayName,
    GraphIPAddress, GraphASN, GraphASNName,
    AADIPAddress, AADASN,
    Location, AADLocation,
    DeviceName, signInSessionStatus,
    RequestMethod, RequestUri, ResponseStatusCode, UserAgent
| order by TimeGenerated desc

Triage steps

  1. 1 Review the ASN mismatch between the initial authentication location and Graph API access location
  2. 2 Check if the user has legitimate reasons to travel between these geographic locations
  3. 3 Investigate the application involved and verify if it's authorized within your environment
  4. 4 Review the Graph API requests to identify what data was accessed during the suspected replay
  5. 5 Check if the UserAgent indicates automated tooling or custom scripts
  6. 6 Verify the token protection status - unbound tokens are easier to replay
  7. 7 Look for other suspicious activity from the same user or application within the same timeframe
  8. 8 If confirmed malicious, revoke the application's access and reset user credentials

True positive example

Example 1

TimeGenerated
06/12/2025, 14:14:07.035
SignInActivityId
70ObFHiCDUW42aMM2OEcAA
Identity
Hunter
AppDisplayName
TruffleHog Test App
GraphIPAddress
79.135.105.18
GraphASN
212238
GraphASNName
Datacamp Limited
AADIPAddress
85.139.240.135
AADASN
2856
Location
UAE North
AADLocation
GB
DeviceName
HUNTERWORK
signInSessionStatus
bound
RequestMethod
GET
RequestUri
https://graph.microsoft.com/v1.0/me/followedSites
ResponseStatusCode
403
UserAgent
data_exfil_tool

Token replay detected from different ASN. The access token was obtained from ASN 2856 (GB) but replayed from ASN 212238 (UAE North/Datacamp Limited), indicating potential token theft and replay attack.

Example 2

TimeGenerated
06/12/2025, 14:14:05.738
SignInActivityId
70ObFHiCDUW42aMM2OEcAA
Identity
Hunter
AppDisplayName
TruffleHog Test App
GraphIPAddress
79.135.105.18
GraphASN
212238
GraphASNName
Datacamp Limited
AADIPAddress
85.139.240.135
AADASN
2856
Location
UAE North
AADLocation
GB
DeviceName
HUNTERWORK
signInSessionStatus
bound
RequestMethod
GET
RequestUri
https://graph.microsoft.com/v1.0/me/drive/recent?%24top=5
ResponseStatusCode
200
UserAgent
data_exfil_tool

Successful token replay accessing user's recent files. The attacker successfully accessed sensitive data from a different geographic location using the stolen token.

Example 3

TimeGenerated
06/12/2025, 14:13:54.940
SignInActivityId
70ObFHiCDUW42aMM2OEcAA
Identity
Hunter
AppDisplayName
TruffleHog Test App
GraphIPAddress
79.135.105.18
GraphASN
212238
GraphASNName
Datacamp Limited
AADIPAddress
85.139.240.135
AADASN
2856
Location
UAE North
AADLocation
GB
DeviceName
HUNTERWORK
signInSessionStatus
bound
RequestMethod
GET
RequestUri
https://graph.microsoft.com/v1.0/me/drive/root/search(q='%7B%7D')?%24top=5
ResponseStatusCode
200
UserAgent
data_exfil_tool

Attacker performing search operations on user's OneDrive from unauthorized location. The custom UserAgent 'data_exfil_tool' combined with ASN mismatch indicates automated data exhilaration activity.

Back to all hunts