NetSPI Demonstrates Microsoft Graph Notifications for Email and Teams Data Exfiltration

Summary
NetSPI demonstrates how attackers with compromised user or service-principal access can use Microsoft Graph Rich Notifications to exfiltrate Outlook snippets and Teams messages, and describes monitoring via the added GraphNotificationsActivityLogs table.
Key points
- With a compromised user token or service principal and the required Graph permissions, an attacker can create Rich Notification subscriptions that send message data to a webhook.
- The demonstration shows Outlook notifications returning up to 255 characters of bodyPreview, while Teams notifications can contain the full message body.
- Repeatedly saving email drafts in chunks can trigger notifications that capture content beyond Outlook’s 255-character preview limit.
- Subscriptions expire after a limited period but can be extended before expiration; persistent access can therefore renew them.
- Administrators can enumerate subscriptions with the Graph PowerShell Get-MgSubscription cmdlet; viewing all tenant subscriptions requires Global Administrator access and Subscription.Read.All.
- MicrosoftGraphActivityLogs can show subscription API operations, while GraphNotificationsActivityLogs records triggered notifications; the article notes that the newer table’s properties are not fully understood or documented.
- After NetSPI’s MSRC disclosure, Microsoft added GraphNotificationsActivityLogs. The article recommends controls including MFA, compliant-device requirements, and blocking device-code authentication.
Article Details
- Attack Vectors
- In the described post-compromise scenario, an attacker with access to a user's Microsoft Graph access and refresh tokens creates Rich Change Notification subscriptions for Outlook emails or Teams messages.
- A subscription directs notifications containing resource data to an externally accessible webhook; the article's example webhook decrypts the payload and stores it in attacker-controlled Cosmos DB.
- A compromised service principal with the required application permissions can subscribe to Teams messages across the organization.
- Subscriptions can be renewed before they expire by an attacker who retains access. The article also demonstrates splitting a long email into draft updates to collect its content in multiple notifications.
- Defensive Notes
- Review current subscriptions using the Get-MgSubscription Graph PowerShell cmdlet; the article says there is no dedicated Entra admin portal blade for listing them.
- Monitor MicrosoftGraphActivityLogs for requests to /v1.0/subscriptions and /beta/subscriptions, which can indicate subscription creation, reads, updates, or deletion.
- Monitor GraphNotificationsActivityLogs for triggered notifications and review the endpoint, subscription type, message information, and SubscriptionIdentity. Correlate SubscriptionIdentity with Get-MgSubscription for parent-subscription details.
- Apply Conditional Access controls to reduce token abuse, including blocking device-code authentication, enforcing MFA, and requiring compliant devices.
- The article notes that Graph activity logs capture subscription API operations, not webhook triggers; GraphNotificationsActivityLogs was added to record triggered notifications.
MITRE ATT&CK
T1059.001 · PowerShellThe service-principal scenario uses a PowerShell script and New-MgSubscription to create a Rich Notification subscription.T1114.002 · Remote Email CollectionThe demonstrated subscriptions collect Outlook email data through Microsoft Graph, including message metadata and bodyPreview content.T1213.005 · Messaging ApplicationsThe demonstrated Rich Notifications collect Teams chat messages, including message bodies, through Microsoft Graph.T1550.001 · Application Access TokenThe user scenario uses a Graph API bearer access token, obtained alongside a refresh token, to create subscriptions.T1567.004 · Exfiltration Over WebhookRich Notification data is sent through Microsoft infrastructure to an externally accessible webhook controlled by the attacker in the described scenario.
People
Dirk-jan MollemaThe article credits him, together with Fabian Bader, with documenting pre-consented permissions in Microsoft first-party applications through Entra Scopes.Fabian BaderThe article credits him, together with Dirk-jan Mollema, with documenting pre-consented permissions in Microsoft first-party applications through Entra Scopes.Jos LiebenThe article cites his work on Graph Change Notifications and says his M365Permissions tool can list current subscriptions in a tenant.Nathan McNultyThe article cites his prior work on webhooks in Microsoft 365 or Graph Change Notifications.
Vendors
Products
Azure Event HubsThese notifications can be directed to external webhook endpoints or Azure Event Hubs/Event Grids.Cosmos DBThis is then pushed to Cosmos DB.Entra IDMicrosoft’s Graph API (graph.microsoft.com) allows users to retrieve data for Entra ID and Microsoft 365.Key VaultThe function is also responsible for grabbing the corresponding private key from a Key Vault to decrypt the encrypted Rich Notification content sent by the Graph API.Microsoft 365 Apps for EnterpriseMicrosoft’s Graph API (graph.microsoft.com) allows users to retrieve data for Entra ID and Microsoft 365.Microsoft GraphWith that in mind, consider this: what if there was a way to exfiltrate emails and messages all via the Microsoft Graph API?OutlookThankfully, I don’t receive that many emails or messages on an average day, but these numbers show how important products like Outlook or Teams are for businesses.TeamsIn the blog, they note that an employee receives on average 117 emails and 153 Teams messages each day.
Tools
Entra ScopesThis has been documented in detail by Fabian Bader and Dirk-jan Mollema with their Entra Scopes app.M365PermissionsJos Lieben’s M365Permissions tool has functionality to list current Change Notifications in a tenant from an Administrator standpoint.roadtxTo simulate this, the roadtx tool (ROADtools) will be used to get tokens.
