Auditing in the Microsoft Graph Mailbox Import Export API
When I previously explored the new Mailbox Import and Export API in the Microsoft Graph, one of the observations I made was the apparent lack of auditing entries. This raised immediate questions that I didn’t fully explore at the time. Recently I've seen some discussions on the topic that lacked a bit of technical depth around how these new endpoints work and what url’s are used and how auditing may appear when this new API is used. Given the scant documentation around the subject the complete picture of this seem a bit cloudy.
To get to the bottom of it, I conducted a some research into both the auditing and activity logs and this post is around the results of this as of June 20th (and it's important to remember that the API is still in beta status which means things can and will change).
TLDR
To summarize, auditing for the Import and Export API is indeed available. ExportItem operations are logged as MailItemsAccessed events (or aggregated)
, and import operations are logged as Create events
within the unified audit log. These audit entries are contingent upon having auditing correctly configured for these events and also having the appropriate M365 licensing. While they may not explicitly denote the Import or Export API’s utilization, they nonetheless provide auditable records(detailed explanation below).
The Microsoft Graph activity logs also offer more detailed coverage of the EndPoint’s usage. Access to these logs necessitates a Microsoft Entra ID P1 or P2 tenant license, alongside an active Azure Subscription, incurring associated operational costs. It is important to note that while the import process itself is not logged in the Graph activity logs due to the specific endpoint and method used, the creation of the import session is recorded. I’ll go in depth on the technical details of this below.
Pre-Requisites
As mentioned there are two locations where you can find information about this Endpoint’s use. The first is in the Exchange Mailbox Audit data in the Unified Audit log and the second is in the Microsoft Graph Activity logs.
Exchange Mailbox Auditing
To enable auditing at this level, you need to be logging MailItemsAccessed
and Create
events. See these Microsoft Learn articles for more information:
I'd also suggest reading all of the articles at https://office365itpros.com/?s=MailItemsAccessed
Exchange audit data can be retrieved and searched in a number of different ways: in the Purview portal, the Search-UnifiedAuditLog
exov3 cmdlet, and also a beta Graph Endpoint. Another less-used method is via the "Office 365 Management Activity API."
Microsoft Graph Activity Logs
For this, you need to have a Microsoft Entra ID P1 or P2 tenant license in your tenant. It also requires an Azure Subscription. The Graph Activity logs are useful as they show direct usage of the ExportItem
operations but offer only limited visibility on the import side. To learn more about setting this up in a tenant , see:
https://learn.microsoft.com/en-us/graph/microsoft-graph-activity-logs-overview
https://practical365.com/securing-microsoft-365-with-graph-activity-logs/
Auditing Details
Export Items
Exchange Mailbox Auditing
Export operations performed through the ExportItem
endpoint are recorded as MailItemsAccessed
events in the Audit log. These audit entries are generated via the Rest API, leveraging a Service Principal configured with either delegated (on behalf of a user) or application permissions. An illustrative example of such an entry would be
The entry above indicates that the ClientApp 14d82eec-204b-4c2f-b7e8-296a70dab67e
(in this case representing the PowerShell Graph SDK) accessed the item(s) through 00000003-0000-0000-c000-000000000000
, which is the first-party Microsoft Graph application. In this instance, the audit also provides details about the item or items involved, aggregated into a single event.
Since this was a batched export, the ClientRequestId
remains consistent across all entries that where included in the same batch. Another key piece of information here is the ImmutableId
, which enables correlation of the message with other related events (regardless of that item being later moved or deleted).
The primary purpose of this MailItemsAccessed
event is for post-mortem analysis: to identify what a malicious actor may have accessed. Therefore, the expectation is that you would first identify the Service Principal used by the compromised entity, and then query the audit logs to determine which items were accessed. From this, you can then infer whether those items were exported, scanned, or subject to other actions.
My take: This new Export endpoint isn't significantly more efficient than other mailbox access protocols like IMAP, EWS, or MAPI when it comes to exporting mainly because of throttling. I've built faster solutions myself in EWS and MAPI that can export at similar if not faster speeds. So in regards to exfiltration if you take a real world scenario of a bad actor intercepting a time limited Access token (e.g., from a cafe wifi), then using that token to export a Mailbox it’s far better to just export using Classic Outlook as this is far more stealthier eg raising fewer alarms. EWS and Graph are better for tenant-wide operations due to their scalability so that would more likely to be used in a persistent threat actor scenario (eg midnight blizzard scenario).
Microsoft Graph Activity logs
The Graph Activity logs provide a clearer view of these Export events. For example
You'll see two export types here: a single request and one from a batch (the clientId
is the same for batch elements).
Importantly, these export request formats differ from standard Graph email requests, which would look like:
/users/mailbox@domain/mailfolders/inbox/messages/{messageid}
in the Export endpoint it will be
admin/exchange/mailboxes/MBX:{MalboxGuid@TenantGuid}/exportItems
To effectively parse these logs for exports from a specific mailbox, you'll need to build of find the correct Identifier for the target mailbox (eg you can’t use the email address or UPN). You can achieve this either by using the Graph API as explained in this post, or by leveraging tools like the ExoV3
cmdlets, for example:
"Mbx:{0}@{1}" -f (Get-EXOMailbox -Identity user@domain.com -Properties ExchangeGuid).ExchangeGuid, (Get-ConnectionInformation).TenantID
An advantage of the Graph activity logs over the unified audit logs is it captures the actual initiating client's IP address for each request (in the unified audit logs for exports it shows the Graph servers as the clientIP), along with a wealth of additional information that aids in correlating with specific sign-in events. Furthermore, you can also track any related events in the admin/exchange/mailboxes/ namespace
which can be CRUD operations on folders or item enumerations which if they are being performed should also be monitored and investigated where necessary.
Importing Items
Exchange Mailbox Auditing for Imports
The import process, unlike most standard Graph endpoints, operates differently. To import items into a mailbox, you follow a two-step procedure:
Create an Import Session: You initiate a Graph API call to create an import session. This call returns a pre-authenticated URL, similar to
https://outlook.office365.com/api/gbeta/Mailboxes('MBX:….')/importItem?authtoken=eyJh…
. This is the only Graph endpoint interaction for an individual item import.Upload Items: You then use this pre-authenticated URL to upload the items directly to the mailbox via an application-specific endpoint, not a standard Graph endpoint.
As a result, the import of an item using this new API is primarily logged in the Unified Audit Log as a Create event associated with the import session. eg
An Undocumented Insight: The Import App ID
(Disclaimer: This information is based on personal observation and is currently undocumented. Its accuracy and longevity are not guaranteed.)
Interestingly, import operations consistently show the ClientAppId
as the first party Microsoft Graph application (00000003-0000-0000-c000-000000000000
), while the AppId
is c999ed3e-27ae-4cb3-b3a2-46b056af63d3
. I've confirmed this AppId
's presence across different tenants for imports.
This indicates c999ed3e-27ae-4cb3-b3a2-46b056af63d3
likely belongs to the internal Import App (possibly residing at https://outlook.office365.com/api/gbeta/
). Searching your audit logs for this specific AppId (in the AppAccessContext)
could be a powerful way to isolate import activity from other Create
operations.
Please verify this in your own environment and let me know your findings!
Microsoft Graph Activity logs
As noted earlier, individual message imports aren't directly logged in the Microsoft Graph Activity logs because they don't originate as Graph requests. What you will find, however, are entries for the request to create an import session. This session creation is a Graph request, and it's the prerequisite for subsequent import requests.
Therefore, if you're looking to audit the import side of this API via Graph activity logs, focus on these import session creation events. They'll show you precisely which applications and clients are initiating import operations.
Beyond the Logs: API Security & Monitoring
The deprecation of EWS underscores a key security principle: "He who never trusts can never be betrayed." EWS's limited OAuth permission scope (just two permissions for delegate and application access) meant any app with an EWS token could access export/import functionalities in EWS.
The Graph API, however, provides specific import and export permissions for both delegated and application contexts. This granular control is a significant security improvement, enabling you to tightly restrict and scrutinize applications. Monitoring your Service Principals—specifically, when and why they are granted these particular Graph permissions—is paramount for preventing misuse. But remember while EWS is still active in your tenant it much more available and harder to track in regards to misuse.