SOP-21: OAuth Illicit Consent Grant Attack Response

·

In an illicit consent grant attack, the adversary registers a malicious OAuth application and crafts a phishing link that sends the victim to Microsoft's legitimate consent prompt. When the user clicks "Accept," they grant the attacker's app persistent access using their own OAuth token — bypassing MFA entirely because Microsoft itself issued the token.

The attack is particularly dangerous because: (1) the token survives password changes unless explicitly revoked, (2) the app operates using Delegated permissions appearing as the legitimate user, and (3) offline_access grants a refresh token that continuously issues new access tokens without further user interaction.

◈ Table of Contents

01 Background 02 Identification 03 Containment 04 Eradication 05 Escalation
01

Background

CONTEXT
B1High-Risk OAuth Permission Scopes
ScopeTypeRisk
offline_accessDelegatedIssues refresh token — persistent access even when user is offline. Always treat as high-risk.
Mail.Read / Mail.ReadWriteDelegatedRead all email including security alerts, password reset emails, MFA codes via email
Files.ReadWrite.AllDelegated/ApplicationRead, create, modify, delete all SharePoint and OneDrive files accessible to the user
Contacts.ReadWriteDelegatedHarvest contact list for further spearphishing; useful for BEC lateral spread
Directory.ReadWrite.AllApplicationRead and modify entire directory — users, groups, roles. Treat as equivalent to admin.
MailboxSettings.ReadWriteDelegatedCreate/modify inbox rules, out-of-office, delegate settings — used for BEC persistence
B2Log Sources
SourceTableKey Operation
Entra ID AuditAuditLogsConsentGranted — user or admin granted consent to an OAuth app
M365 Unified Audit LogOfficeActivityConsentGranted, FileSyncDownloadedFull, SearchQuery (attacker using Mail API)
SP Sign-in LogsAADServicePrincipalSignInLogsThe OAuth app authenticating on behalf of user after consent granted
02

Identification

INVESTIGATE
OAuth Consent Grant — Investigation Workflow
I1Detect ConsentGranted EventsKQL + SPL
KQL — Sentinel: All consent grants in last 7 days
AuditLogs | where TimeGenerated > ago(7d) | where OperationName == "Consent to application" | extend UserUPN = tostring(InitiatedBy.user.userPrincipalName) | extend AppName = tostring(TargetResources[0].displayName) | extend AppId = tostring(TargetResources[0].id) | extend Scopes = tostring(TargetResources[0].modifiedProperties[0].newValue) // High-risk scope filter | where Scopes has_any ("offline_access","Mail.Read","Mail.ReadWrite", "Files.ReadWrite","Contacts.ReadWrite", "MailboxSettings.ReadWrite","Directory.ReadWrite.All") | project TimeGenerated, UserUPN, AppName, AppId, Scopes | order by TimeGenerated desc
KQL — How many users consented to the same suspicious app?
// Find campaign scope — multiple users consenting same app let suspicious_app = "SuspiciousAppName"; // set to app name from I1 AuditLogs | where TimeGenerated > ago(30d) | where OperationName == "Consent to application" | extend UserUPN = tostring(InitiatedBy.user.userPrincipalName) | extend AppName = tostring(TargetResources[0].displayName) | where AppName =~ suspicious_app | summarize AffectedUsers=make_set(UserUPN), ConsentCount=count() by AppName | project AppName, ConsentCount, AffectedUsers
SPL — Splunk: Consent grant detection
index=azure sourcetype=azure:aad:audit OperationName="Consent to application" | spath InitiatedBy.user.userPrincipalName OUTPUT UserUPN | spath TargetResources{}.displayName OUTPUT AppName | spath TargetResources{}.modifiedProperties{}.newValue OUTPUT Scopes | where Scopes LIKE "%offline_access%" OR Scopes LIKE "%Mail.Read%" | table _time, UserUPN, AppName, Scopes | sort -_time

An OAuth app with offline_access can access data indefinitely without the user being logged in. The refresh token issued at consent time will continue generating new access tokens until the consent is explicitly revoked — not until the password is reset.

03

Containment

STOP IT
C1Revoke Consent & Block App Tenant-WideImmediate
  • 1
    Revoke consent for all affected users: Entra ID → Enterprise applications → [Malicious App] → Users and groups → Remove all users. This revokes the delegated permission grant.
  • 2
    Disable the app tenant-wide: Enterprise applications → [App] → Properties → Enabled for users to sign in → NO. Prevents any further use of existing tokens.
  • 3
    Block the app's publisher domain via Tenant restrictions if operating through a specific Azure AD tenant. Alternatively, block at the CA policy level using app filter conditions.
  • 4
    Check for follow-on inbox rules on affected users' mailboxes (cross-reference SOP-10 BEC) — attacker may have created forwarding rules using the Mail access.

Run the OAuth app risk review in Microsoft Defender for Cloud Apps (MDCA): Investigate → OAuth apps → filter by Permissions level = High and Community use = Rare. MDCA assigns a risk score to each OAuth app based on publisher reputation, permission scope, and adoption rate — use it to triage multiple consent events quickly.

04

Eradication

CLEAN UP
E1Data Access Audit & Tenant Hardening
  • 1
    Audit M365 Unified Audit Log for FileDownloaded, SearchQuery, and MailItemsAccessed events from the malicious app's client ID during the window between consent and revocation.
  • 2
    Delete the rogue app registration from Entra ID entirely if it was registered in your tenant. If it was an external app, report it to Microsoft via the security reporting portal.
  • 3
    Enable admin consent requirement: Entra ID → User settings → Enterprise applications → Users can consent to apps accessing company data → NO. This forces all OAuth app consents through an admin approval workflow.
  • 4
    Configure the App Governance add-on in MDCA to auto-disable apps that exceed a threshold of unusual API calls or data access volume.
  • 5
    Brief affected users — explain what data the app may have accessed (email, files, contacts) and advise on BEC warning signs if mail was accessed.
Eradication Complete When
  • Consent revoked for all affected users; app disabled tenant-wide
  • No further AADServicePrincipalSignInLogs entries from the app
  • Admin consent workflow enabled — users cannot self-consent to new apps
  • Data access window documented; breach notification assessment complete
  • Phishing email delivering consent link removed from all inboxes via ZAP
05

Escalation

TIERS
ESC1Escalation Tiers
TierTriggerAction
L1 → L2Single user, low-permission scopes (profile/openid only), no data access confirmedRevoke consent, disable app, document. Educate user on OAuth phishing.
L2 → IR + CISOMail.Read or Files.ReadWrite granted; app used the access; multiple users affected; inbox rules foundData breach assessment. Engage legal for notification assessment. Full incident declared.
IR → MicrosoftMalicious app registered within your own tenant by an attacker who gained admin accessApp deletion + tenant security review. Submit malicious app to Microsoft MSRC.

Authorized security research & penetration testing only. Unauthorized use is illegal. Authored by Rudra Verma | Senior Security Architect | CyberHawk Consultancy.

◈ Stay Connected

Follow CyberHawk Threat Intel for SOC SOPs, threat intelligence, and hands-on analyst tooling.

Website YouTube Twitter / X TikTok Telegram
All SOPs Blog Courses

"They can't exploit you if you are the Exploit."