Query Details

13 O Auth Consent Immediate Abuse

Query

id: a8b4c6d7-e2f3-5a9b-0c1d-2e3f4a5b6c7d
name: OAuth App Consent Followed by Immediate Silent Authentication
version: 1.0.0
kind: Scheduled
description: |
  Detects when a user grants consent to an OAuth application in Azure AD (recorded in
  Audit Logs) and that same app immediately begins generating non-interactive token
  refreshes within 24 hours. This is the signature of illicit consent grant attacks
  where an attacker tricks a user into granting a malicious app persistent access to
  their mailbox, files, or other sensitive resources.
  MITRE ATT&CK: T1528 (Steal Application Access Token), T1566 (Phishing)
severity: High
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AADNonInteractiveUserSignInLogs
      - AuditLogs
queryFrequency: 1h
queryPeriod: 24h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CredentialAccess
  - Persistence
  - InitialAccess
relevantTechniques:
  - T1528
  - T1566
  - T1078
query: |
  let RecentConsents =
      AuditLogs
      | where TimeGenerated > ago(24h)
      | where OperationName has_any (
          "Consent to application",
          "Add app role assignment",
          "Add delegated permission grant"
        )
      | extend ActorUPN    = tostring(InitiatedBy.user.userPrincipalName)
      | extend AppId       = tostring(TargetResources[0].id)
      | extend AppName     = tostring(TargetResources[0].displayName)
      | where isnotempty(ActorUPN)
      | project ConsentTime=TimeGenerated, ActorUPN, AppId, AppName, OperationName;
  AADNonInteractiveUserSignInLogs
  | where TimeGenerated > ago(24h)
  | where ResultType == 0
  | join kind=inner RecentConsents
      on $left.UserPrincipalName == $right.ActorUPN, $left.AppId == $right.AppId
  | where TimeGenerated > ConsentTime
     and  (TimeGenerated - ConsentTime) < 24h
  | summarize
      NI_Count     = count(),
      IPs          = make_set(IPAddress),
      Countries    = make_set(Location),
      FirstUse     = min(TimeGenerated)
    by UserPrincipalName, AppName, AppId, ConsentTime, OperationName
  | extend IPAddress = tostring(IPs[0])
  | order by ConsentTime desc
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: UserPrincipalName
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPAddress
  - entityType: CloudApplication
    fieldMappings:
      - identifier: AppId
        columnName: AppId
      - identifier: Name
        columnName: AppName
customDetails:
  AppName: AppName
  ConsentTime: ConsentTime
  SignInsAfterConsent: NI_Count
  Countries: Countries
alertDetailsOverride:
  alertDisplayNameFormat: "Illicit OAuth Consent - {{UserPrincipalName}} granted access to {{AppName}} which immediately began silent auth"
  alertDescriptionFormat: "User {{UserPrincipalName}} consented to app '{{AppName}}' which then generated {{NI_Count}} non-interactive sign-ins within 24 hours. Investigate whether consent was phishing-induced."
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AnyAlert
    groupByEntities:
      - Account
    groupByAlertDetails: []
    groupByCustomDetails: []

Explanation

This query is designed to detect potential security threats in Azure Active Directory by identifying suspicious OAuth app consent activities. Here's a simplified explanation:

  1. Purpose: The query looks for instances where a user grants consent to an OAuth application, and then that application starts making non-interactive sign-ins (silent authentications) within 24 hours. This pattern can indicate a malicious app trying to gain unauthorized access to user data, often through phishing attacks.

  2. Data Sources: It uses data from Azure AD Audit Logs and Non-Interactive User Sign-In Logs to track user consent actions and subsequent app activities.

  3. Process:

    • It first identifies recent consents given to applications by users within the last 24 hours.
    • Then, it checks if these applications have started making non-interactive sign-ins within the same 24-hour period after consent was granted.
    • It counts these sign-ins and collects information about the IP addresses and locations from which these sign-ins originated.
  4. Output: The query generates a summary of these activities, including the number of sign-ins, the IP addresses used, and the countries from which the sign-ins occurred. It orders the results by the time of consent.

  5. Alerting: If any such suspicious activity is detected, an alert is generated with details like the user who granted consent, the app name, and the number of sign-ins. The alert suggests investigating whether the consent was obtained through phishing.

  6. Severity and Tactics: The query is marked with high severity and is associated with tactics like Credential Access, Persistence, and Initial Access, aligning with specific MITRE ATT&CK techniques related to stealing application access tokens and phishing.

  7. Incident Management: If an alert is triggered, it can create an incident in the security system, with options for grouping related alerts to manage them efficiently.

Overall, this query helps security teams identify and respond to potential illicit consent grant attacks, protecting sensitive resources from unauthorized access.

Details

David Alonso profile picture

David Alonso

Released: May 29, 2026

Tables

AADNonInteractiveUserSignInLogsAuditLogs

Keywords

OAuthApplicationAzureADAuditLogsUserMailboxFilesResourcesTokenPhishingCredentialAccessPersistenceInitialAccessAccountIPCloudApplication

Operators

let|where>ago()has_any()extendtostring()isnotempty()project==joinkind=inneron$and-<summarizecount()make_set()min()byorder bydesc

Actions