Guest users who have been invited but have not redeemed their invite within an unusually long period may indicate potential misuse or reconnaissance by an adversary seeking to exploit long-term access. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify and mitigate potential lateral movement or persistence tactics.
KQL Query
let lookback = 14d;
let invitethreshold = 5d;
// Collect external user invitations
let ExtUserInvites = AuditLogs
| where TimeGenerated > ago(lookback)
| where Category =~ "UserManagement"
| where OperationName =~ "Invite external user"
| extend TargetUPN = tostring(TargetResources[0].["userPrincipalName"])
| extend InviteInitiator = tostring(InitiatedBy.["user"].["userPrincipalName"]) , IPAddress = tostring(InitiatedBy.["user"].["ipAddress"])
| where isnotempty(InviteInitiator)
| extend InviteTime = TimeGenerated;
// Collect redeem events
let ExtUserRedeem = AuditLogs
| where TimeGenerated > ago(lookback)
| where Category =~ "UserManagement"
| where OperationName =~ "Redeem external user invite"
| where Result =~ "success"
| extend InviteInitiator = tostring(InitiatedBy.["user"].["userPrincipalName"])
| extend Target = tostring(TargetResources[0].["userPrincipalName"])
| extend TargetUPN = tostring(extract(@"UPN\:\s(.+)\,\sEmail",1,Target))
| where isnotempty(Target);
// Find invites who have not been redeemed since long time.
ExtUserInvites
| join kind=leftanti ( ExtUserRedeem ) on TargetUPN
| where InviteTime > ago(invitethreshold)
| project TimeGenerated
id: 1ad620f0-fee4-4bb7-a2b3-62af7f18332b
name: Invited Guest User but not redeemed Invite for longer period.
description: |
'This query will look for events where guest user was invited but has not accepted/redeemed invite for unusually longer period.
Any invites not redeemed for longer period of time can be misused and pose risk if suspiciously redeemed in other ways'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- AuditLogs
tactics:
- InitialAccess
relevantTechniques:
- T1078.004
tags:
- GuestorExternalIdentities
query: |
let lookback = 14d;
let invitethreshold = 5d;
// Collect external user invitations
let ExtUserInvites = AuditLogs
| where TimeGenerated > ago(lookback)
| where Category =~ "UserManagement"
| where OperationName =~ "Invite external user"
| extend TargetUPN = tostring(TargetResources[0].["userPrincipalName"])
| extend InviteInitiator = tostring(InitiatedBy.["user"].["userPrincipalName"]) , IPAddress = tostring(InitiatedBy.["user"].["ipAddress"])
| where isnotempty(InviteInitiator)
| extend InviteTime = TimeGenerated;
// Collect redeem events
let ExtUserRedeem = AuditLogs
| where TimeGenerated > ago(lookback)
| where Category =~ "UserManagement"
| where OperationName =~ "Redeem external user invite"
| where Result =~ "success"
| extend InviteInitiator = tostring(InitiatedBy.["user"].["userPrincipalName"])
| extend Target = tostring(TargetResources[0].["userPrincipalName"])
| extend TargetUPN = tostring(extract(@"UPN\:\s(.+)\,\sEmail",1,Target))
| where isnotempty(Target);
// Find invites who have not been redeemed since long time.
ExtUserInvites
| join kind=leftanti ( ExtUserRedeem ) on TargetUPN
| where InviteTime > ago(invitethreshold)
| project TimeGenerated
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: InviteInitiator
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPAddress
version: 1.0.0
| Sentinel Table | Notes |
|---|---|
AuditLogs | Ensure this data connector is enabled |
Scenario: Scheduled Job Invites for System Maintenance
Description: A system maintenance or backup job may invite a guest user (e.g., a third-party service account) for a specific task, but the invite is not redeemed immediately due to scheduling delays.
Filter/Exclusion: Exclude invites associated with known system maintenance tasks (e.g., tool_name: Azure Backup, tool_name: AWS Backup, tool_name: SCCM) or use a custom field like invite_purpose = "system_maintenance".
Scenario: Admin-Initiated Invite for Future Use
Description: An admin may invite a guest user for a future collaboration or project, but the invite is not redeemed immediately.
Filter/Exclusion: Exclude invites created by admin users (e.g., user_type = "admin") or use a custom field like invite_status = "pending_approval".
Scenario: Invited User is on Leave or Unavailable
Description: A guest user may have been invited but is currently on leave or unavailable, leading to a delay in redemption.
Filter/Exclusion: Exclude invites where the user is marked as on leave (e.g., user_status = "on_leave") or use a custom field like user_availability = "unavailable".
Scenario: Invited User is Testing Access Before Redemption
Description: A user may be invited to test access to a system or application but has not yet redeemed the invite to evaluate the environment.
Filter/Exclusion: Exclude invites with a custom field like invite_purpose = "access_test" or where the user has a known testing role (e.g., user_role = "tester").
Scenario: Invited User is Part of a Multi-Step Onboarding Process
Description: A guest user may be invited as