Eduard Arbona — identity security engineer. Contributions merged into Maester and Azure Sentinel; author of EntraTripwire.
Most people picture an account takeover as a stolen password. In Microsoft Entra ID, one of the quietest and most durable takeovers never touches the password at all. It is the illicit consent grant, and if you only watch for failed sign-ins you will miss it completely.
Here is how it works, why multi-factor authentication does not save you, and the exact signal I use to catch it.
The attack, start to finish
An attacker registers an application in their own tenant, usually multi-tenant so it can be consented from anywhere. They craft a normal OAuth 2.0 authorization URL that asks for delegated permissions such as Mail.Read, Mail.Send, Files.Read.All, and critically offline_access.
Then they phish a link. The victim clicks it and lands on the real login.microsoftonline.com page. They sign in, they pass MFA, everything looks legitimate, because it is. The only unusual part is a consent screen asking them to let "Some App" read their mail. People click through consent screens all day.
The moment the victim consents, Entra ID creates a service principal and an OAuth permission grant in the victim's own tenant. The application receives an access token, and because of offline_access, a refresh token. From that point the attacker reads the mailbox through Microsoft Graph using tokens, on their own schedule, from their own infrastructure.
Why your usual defenses do not fire
This is the part that surprises people:
- The password was never captured, so a password reset does not revoke access. The refresh token keeps working.
- MFA already succeeded during the consent flow. Re-prompting for MFA later does nothing to a token refresh.
- There is no malware on any endpoint, so EDR has nothing to find.
- Sign-in logs look normal. The victim had a legitimate interactive sign-in. The ongoing access shows up as app-only Graph calls, not as suspicious logins.
Revoking this requires removing the grant and the service principal. Until you do, the attacker has quiet, persistent mailbox access that survives most of your incident response reflexes.
The signal I actually watch
The event you want lives in the Entra ID audit log, not the sign-in log. The operation is "Consent to application" (and the related delegated permission grant events), available through Microsoft Graph at auditLogs/directoryAudits and surfaced in Microsoft Sentinel as the AuditLogs table.
A consent is not automatically malicious. What makes one worth an alert is the combination:
- The app is not from a verified publisher.
- The granted delegated scopes include mail or file access plus
offline_access(persistence is the tell). - The consent was performed by an ordinary user, not an admin, often to an app that was registered very recently.
- The app's reply URL points to an unfamiliar domain.
Here is the shape of the Sentinel KQL I use to pull the high-signal cases out:
AuditLogs
| where OperationName == "Consent to application"
| mv-expand target = TargetResources
| mv-expand mod = target.modifiedProperties
| where tostring(mod.displayName) == "ConsentAction.Permissions"
| extend grantedPerms = tostring(mod.newValue)
| where grantedPerms has "offline_access"
and (grantedPerms has "Mail.Read"
or grantedPerms has "Mail.ReadWrite"
or grantedPerms has "Mail.Send")
| extend actor = tostring(InitiatedBy.user.userPrincipalName)
| project TimeGenerated, actor, grantedPerms, Result
One thing to check first: the exact shape of modifiedProperties varies between tenants and log versions, so treat the parsing as a starting point and confirm the field layout in your own AuditLogs before you trust the rule. I validate my detections against the official KQL parser and map each one to a MITRE ATT&CK technique so I know what I am actually covering and what I am not.
Closing the door, not just watching it
Detection is half the job. The configuration change that removes most of the risk is tightening the consent policy:
- Restrict user consent to verified publishers and low-risk permissions only, and route everything else through an admin consent request workflow. A human reviews before mail access is ever granted.
- Review enterprise applications and their granted permissions on a schedule. Old, forgotten, over-permissioned apps are exactly what an attacker hides behind.
-
Alert on every new consent to an app requesting mail or
offline_access, using the query above.
I also take a deception angle with a tool I published, EntraTripwire: plant decoy applications and credentials that nothing legitimate should ever consent to or touch, and score whoever does. A consent grant against a decoy app is a near-zero-false-positive signal that someone is probing your tenant.
Why this matters more than it looks
The illicit consent grant is attractive to attackers precisely because it is boring to defenders. It does not trip the alarms everyone tunes first. It is a configuration-and-token problem wearing the clothes of a normal user action.
If you run Entra ID, two things are worth doing this week: pull your last ninety days of "Consent to application" events and look for mail plus offline_access grants to unverified apps, and check whether user consent is still wide open in your tenant. Both take minutes. Both can surface a problem that your password policy and your MFA were never going to catch.
I build read-only security tooling for Microsoft Entra ID and M365. The consent-monitoring work in this article is open source on my GitHub (earbona23), and a related analytic rule is merged into Microsoft's Azure Sentinel repository.
Top comments (0)