One Click. Permanent Inbox Access. MFA Bypassed.
An employee at your organization connected ChatGPT to their work account. A consent popup appeared. They clicked "Accept." That single click gave ChatGPT — and anyone who compromises that OAuth token — permanent, silent read access to every email in their inbox.
No password needed. No MFA prompt. No login alert. The token just works, quietly, in the background, forever — until someone revokes it.
This isn't a vulnerability in ChatGPT. It's a design flaw in how Microsoft Entra ID handles OAuth consent — and it affects every Microsoft 365 organization on the planet.
How It Works
Step 1: The Consent Screen
When a user connects ChatGPT (or any third-party app) to their Microsoft 365 account, Entra ID presents an OAuth consent screen:
"ChatGPT" would like to:
✓ Read your mail
✓ Maintain access to data you have given it access to
✓ View your basic profile
[Accept] [Cancel]
The critical permission is Mail.Read — access to read every email in the user's mailbox via Microsoft Graph API.
Most users click Accept without reading. Most organizations allow non-admin users to grant these permissions by default.
Step 2: Service Principal Creation
Once the user consents, Entra ID creates a Service Principal — a persistent digital identity for the application. This service principal receives an OAuth token that:
- Never expires (until explicitly revoked)
- Bypasses MFA — it's a token, not a login
- Works in the background — no user interaction needed
- Survives password changes — the token is independent of the user's credentials
The app doesn't log in as the user. It authenticates as itself, with delegated permissions to read the user's mail.
Step 3: Silent Email Access
With the Mail.Read scope and offline_access, the application can:
GET https://graph.microsoft.com/v1.0/me/messages
Authorization: Bearer {oauth_token}
→ Returns every email in the user's mailbox
→ No audit trail in the user's sign-in logs
→ No MFA challenge
→ No notification to the user
This isn't hacking. This is the OAuth 2.0 protocol working exactly as designed.
Why This Is Dangerous
The Legitimate Scenario
ChatGPT (App ID: e0476654-c1d5-430b-ab80-70cbd947616a) is a legitimate application from OpenAI. When a user connects it to their work account, OpenAI's servers can read their email to provide AI-assisted features.
This is the intended behavior. The problem is what happens next.
The Attack Scenario
An attacker doesn't need to compromise ChatGPT. They just need to:
- Create a malicious app that looks like a legitimate service
- Send a phishing link with an OAuth consent URL
- User clicks Accept on the consent screen
- Attacker's app gets a persistent token with Mail.Read access
- Attacker reads every email — silently, indefinitely
Or even simpler:
- Compromise any app that already has Mail.Read consent
- Use its existing token to read emails
- No phishing needed — the consent was already granted
Business Email Compromise (BEC) Chain
OAuth consent granted
↓
Attacker reads inbox silently for weeks
↓
Identifies pending wire transfer ($450,000 invoice)
↓
Learns communication patterns between CFO and vendor
↓
Sends spoofed email at the right moment:
"Please update our bank details for this payment"
↓
Money gone. No malware. No suspicious login.
The FBI's IC3 reported $2.9 billion in BEC losses in 2023 alone. OAuth consent abuse makes BEC reconnaissance trivially easy.
The Scale of the Problem
In a typical Microsoft 365 tenant:
- Dozens of third-party apps have OAuth consent
- Most users can grant consent without admin approval (default setting)
- Nobody audits which apps have which permissions
- Tokens persist until manually revoked
- No expiration by default on delegated permissions
Red Canary researchers found that most organizations have no visibility into which applications have been granted email access through OAuth consent.
Detection
Audit Log Monitoring
The two critical events to monitor in Entra ID audit logs:
Operation: "Consent to application"
Operation: "Add service principal"
These events show exactly who authorized which application and when.
KQL Detection Query (Microsoft Sentinel)
AuditLogs
| where OperationName == "Consent to application"
| extend AppName = tostring(TargetResources[0].displayName)
| extend Permissions = tostring(TargetResources[0].modifiedProperties[0].newValue)
| where Permissions has_any ("Mail.Read", "Mail.ReadWrite", "Files.Read", "Chat.Read")
| extend ConsentUser = tostring(InitiatedBy.user.userPrincipalName)
| project TimeGenerated, ConsentUser, AppName, Permissions
| sort by TimeGenerated desc
High-Risk Permission Alert
AuditLogs
| where OperationName == "Consent to application"
| extend AppId = tostring(TargetResources[0].id)
| extend OrgId = tostring(AdditionalDetails[0].value)
| where OrgId != "<your-tenant-id>" // External apps only
| extend Permissions = tostring(TargetResources[0].modifiedProperties[0].newValue)
| where Permissions has_any ("Mail.Read", "Mail.ReadWrite", "Mail.Send")
| project TimeGenerated, AppId, Permissions, InitiatedBy
Graph API — List All Consented Apps
# List all OAuth2 permission grants in your tenant
Get-MgOauth2PermissionGrant -All | Where-Object {
$_.Scope -match 'Mail.Read|Mail.ReadWrite|Mail.Send'
} | Select-Object ClientId, PrincipalId, Scope, ConsentType
This single command shows every application with email access in your entire organization.
Remediation
Immediate: Revoke Suspicious Consents
# Find and revoke a specific app's consent
$grants = Get-MgOauth2PermissionGrant -All | Where-Object {
$_.ClientId -eq "<suspicious-app-id>"
}
$grants | ForEach-Object {
Remove-MgOauth2PermissionGrant -OAuth2PermissionGrantId $_.Id
}
Preventive: Restrict User Consent
In Entra ID → Enterprise Applications → Consent and permissions:
| Setting | Recommended Value |
|---|---|
| Users can consent to apps | No |
| Users can consent to apps from verified publishers | For low-risk permissions only |
| Admin consent required for | Mail.Read, Files.ReadWrite, Chat.Read |
| Admin consent workflow | Enabled (users request, admins approve) |
Ongoing: Audit Schedule
- Weekly: Review new "Consent to application" audit events
-
Monthly: Enumerate all OAuth grants with
Get-MgOauth2PermissionGrant - Quarterly: Full review of all service principals and their permissions
- Immediately: Investigate any consent for Mail.Read/Write from unknown apps
MITRE ATT&CK Mapping
| Technique | ID | Usage |
|---|---|---|
| Steal Application Access Token | T1528 | OAuth token persists without MFA |
| Application Access Token | T1550.001 | Token reuse for Graph API access |
| Email Collection | T1114.002 | Mail.Read permission abuse |
| Phishing: Spearphishing Link | T1566.002 | Consent phishing via OAuth URL |
| Valid Accounts: Cloud Accounts | T1078.004 | Service principal persistence |
The Bottom Line
The OAuth consent screen is the new phishing email. It looks legitimate, it asks for permission politely, and it grants permanent silent access that survives every security control you've deployed.
Check your tenant right now:
Get-MgOauth2PermissionGrant -All | Where-Object {
$_.Scope -match 'Mail'
} | Measure-Object
If that number surprises you, you have work to do.
Your users didn't get phished. They didn't click a malicious link. They just connected an AI tool to their work account — and gave away the keys to the inbox.
Need help auditing OAuth permissions across your Microsoft 365 tenant? Request a free penetration test at theinsider-x.com — currently in open beta.
Sources: Red Canary, Hackread, CybersecurityNews, GBHackers, Microsoft Entra ID Documentation
MITRE ATT&CK: T1528, T1550.001, T1114.002, T1566.002, T1078.004
Top comments (0)