Query Details
id: 92824ea9-7f37-4bf9-b4bf-45e7c82a6b46
name: Token Replay from workload identity with privileges in Microsoft Entra or Microsoft 365 (WorkloadIdentityInfo)
version: 1.0.0
kind: Scheduled
description: Detected indicator of token replay attack by using the following pattern. A token has been used for activity on Microsoft Graph API from a different IP address than during the sign-in process. Severity is set to "high" if workload identity has privileges on Control Plane.
severity: Medium
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- CredentialAccess
relevantTechniques:
- T1528
query: |-
let azure_ranges = externaldata(changeNumber: string, cloud: string, values: dynamic)
["https://raw.githubusercontent.com/microsoft/mstic/master/PublicFeeds/MSFTIPRanges/ServiceTags_Public.json"] with(format='multijson')
| mv-expand values
| mv-expand values.properties.addressPrefixes
| mv-expand values_properties_addressPrefixes
| summarize by tostring(values_properties_addressPrefixes)
| extend isipv4 = parse_ipv4(values_properties_addressPrefixes)
| extend isipv6 = parse_ipv6(values_properties_addressPrefixes)
| extend ip_type = case(isnotnull(isipv4), "v4", "v6")
| summarize make_list(values_properties_addressPrefixes) by ip_type;
MicrosoftGraphActivityLogs
| project TimeGenerated, RequestId, ApiVersion, RequestMethod, ResponseStatusCode, ActivityIpAddress = IPAddress, UserAgent, RequestUri, Roles, AppId, Wids, SignInActivityId, ApplicationId = AppId, Scopes, Location
| join kind=inner (union AADServicePrincipalSignInLogs, AADManagedIdentitySignInLogs
| project ConditionalAccessPolicies, ConditionalAccessStatus, ServicePrincipalCredentialKeyId, SignInIpAddress = IPAddress, UniqueTokenIdentifier, Type
// Correlation between Activity and Sign-in based on Unique Token Identifier
) on $left.SignInActivityId == $right.UniqueTokenIdentifier
// AADManagedIdentitySignInLogs does not include SignInIpAddress
| where ActivityIpAddress != SignInIpAddress and isnotempty(SignInIpAddress)
| extend isipv4 = parse_ipv4(ActivityIpAddress)
| extend ip_type = case(isnotnull(isipv4), "v4", "v6")
| join kind=fullouter (azure_ranges) on ip_type
| extend ipv6_match = ipv6_is_in_any_range(ActivityIpAddress, list_values_properties_addressPrefixes)
| extend ipv4_match = ipv4_is_in_any_range(ActivityIpAddress, list_values_properties_addressPrefixes)
| extend IpAddressType = iff(ipv4_match or ipv6_match, "Azure Public IP", "None Azure IP")
| where isnotempty(ApplicationId)
| join kind=leftouter(
PrivilegedWorkloadIdentityInfo
| project
WorkloadIdentityName,
WorkloadIdentityType,
ApplicationObjectId,
ServicePrincipalObjectId,
ApplicationId,
IsFirstPartyApp,
EntraIdRoles,
AppRolePermissions,
WorkloadIdClassification = EnterpriseAccessModelTiering
)
on ApplicationId
| extend Severity = iff(WorkloadIdClassification contains "ControlPlane", "High", "Medium")
suppressionEnabled: false
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 5h
matchingMethod: Selected
groupByEntities:
- CloudApplication
groupByAlertDetails: []
groupByCustomDetails: []
eventGroupingSettings:
aggregationKind: AlertPerResult
alertDetailsOverride:
alertDisplayNameFormat: Token Replay from workload identity with {{WorkloadIdClassification}} privileges in Microsoft Entra or Microsoft 365
alertDescriptionFormat: Activity of {{WorkloadIdentityName}} from IPAddress ({{ActivityIpAddress}}) to Microsoft Graph API with privileges on {{WorkloadIdClassification}} has been detected which is different than the IP address from sign-in event.
alertSeverityColumnName: Severity
alertDynamicProperties: []
customDetails:
WorkloadIdentityName: WorkloadIdentityName
WorkloadIdentityType: WorkloadIdentityType
ServicePrincipalId: ServicePrincipalObjectId
ApplicationId: ApplicationId
CredentialKeyId: ServicePrincipalCredentialKeyId
IsFirstPartyApp: IsFirstPartyApp
PrivilegedAccess: WorkloadIdClassification
EntraDirectoryRoles: EntraIdRoles
MSGraphRoles: AppRolePermissions
ConditionalAccess: ConditionalAccessStatus
MSGraphUri: RequestUri
MSGraphMethod: RequestMethod
UserAgent: UserAgent
Location: Location
entityMappings:
- entityType: CloudApplication
fieldMappings:
- identifier: Name
columnName: WorkloadIdentityName
- entityType: CloudApplication
fieldMappings:
- identifier: AppId
columnName: ApplicationId
- entityType: IP
fieldMappings:
- identifier: Address
columnName: ActivityIpAddress
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SignInIpAddress
suppressionDuration: 5h
This query detects a token replay attack on Microsoft Graph API. It checks if a token has been used from a different IP address than during the sign-in process. The severity is set to medium, but it can be high if the workload identity has privileges on the Control Plane. The query frequency and period are both set to 1 hour. The query retrieves Azure IP ranges and then joins the MicrosoftGraphActivityLogs with AADServicePrincipalSignInLogs and AADManagedIdentitySignInLogs to correlate activity and sign-in based on a unique token identifier. It filters out activity with different IP addresses and joins with PrivilegedWorkloadIdentityInfo to get additional information. The query also includes incident configuration and alert details override.

Thomas Naunheim
Released: November 20, 2023
Tables
Keywords
Operators