Introduction
Security teams depend on logs to tell them what happened, when, and how. But what happens when the logs are incomplete—or worse, misleading?
Microsoft environments are a common target for attackers and many organizations rely on their services. Microsoft’s activity logs are utilized to gain insight into malicious activity to assess scale and determine next steps. Yet crucial information is often invisible, making these threats more difficult to detect and triage.
In this blog, we’ll dissect the limitations of Microsoft’s activity logs, walk through real-world simulations using the msInvader tool, and highlight what gets seen—and what silently slips through the cracks.
Overview of MS Activity Logs
Microsoft’s Office 365 (M365) and Graph APIs are the backbone of log-based detection for the Microsoft suite.
M365 management API audit logs are divided into the following classifications:
- Audit.AzureActiveDirectory
- Audit.Exchange
- Audit.SharePoint
- Audit.General
- DLP.All
Digging a little deeper, some unsettling realities emerge. Microsoft’s documentation (ref: https://learn.microsoft.com/en-us/office/office-365-management-api/office-365-management-activity-api-reference#working-with-the-office-365-management-activity-api) describes the following issues:
- Content blobs can take up to 12 hours to appear.
- Events in later blobs may predate those in earlier ones.
- Logs often miss critical events—especially reconnaissance and failed attack attempts.
Ref: https://learn.microsoft.com/en-us/office/office-365-management-api/office-365-management-activity-api-reference#working-with-the-office-365-management-activity-api
These aren’t edge cases. They’re systemic blind spots.
Microsoft’s GraphAPI provides ‘auditLog’ endpoints for directoryAudits and signIns as well as customSecurityAttributeAudits and provisioning which are still in beta. (ref: https://learn.microsoft.com/en-us/graph/api/resources/azure-ad-auditlog-overview?view=graph-rest-1.0)
Some events may be available from both sources, for example, authentication or sign-in logs, however each source has a different format.

Microsoft 365 events on the left have key differences from the Graph API entry on the right.
- Two fields for source IP address: ActorIpAddress vs. ipAddress
- The timestamps are formatted differently, missing the timezone in Microsoft365 events.
- The Microsoft Audit logs include additional request information such as the User Agent.
- Microsoft Audit logs include the Operation/action of the event. Graph API logs don’t include this.
- GeoIP information is included about the source client in Graph API logs
Meet msInvader: A Reality Check for Defenders
To test the boundaries of Microsoft’s visibility, we ran a series of attack simulations using msInvader (ref: https://github.com/mvelazc0/msInvader), a red team tool packed with over 20 post-auth techniques.
Using common endpoints like Graph API, Exchange Web Services (EWS), and the REST API, msInvader can:
- Enumerate users, groups, roles, and apps
- Read emails, reset passwords, or forward inboxes
- Attempt privilege escalation via mailbox or folder delegation
Let’s break down what we saw—and what we didn’t.
Enumeration: The Silent Operator
Technique: enumerate_users
API Call: GET /v1.0/users
Result: 24 users successfully enumerated
Logged? ❌ No trace in either Graph or O365 logs
Reconnaissance is a common first step to gather information about the environment. msInvader has multiple techniques for enumeration. Running the ‘enumerate_users’ technique which uses the Graph API endpoint.

We can see that msInvader was able to successfully pull a list of users from the environment. Both Graph and Office 365 logs only provide authentication logs.

This raises a few questions: Why are there ‘UserLoginFailed’ events and a ‘UserLoggedIn’ event? Why are there two ‘Entra ID Sign-In’ events? Where is the log for the user enumeration query? Let’s take a step back and do a quick overview of the authentication process.
msInvader has the option to authenticate using MFA by using the ‘device_code’ authentication type in its configuration. This allows the attacker to log in via a browser with a provided code.

Login proceeds normally from here and execution of msInvader automatically continues.

Getting back to the previous questions:
Why is there a ‘UserLoginFailed’ event?
- If we look at the raw event, we see the ‘ErrorNumber’ is ‘50199’ and the ‘LogonError’ is ‘CmsiInterrupt’. Microsoft’s description for this error(ref: https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes#aadsts-error-codes) :

This means the authentication process was interrupted to add an additional confirmation step for the app. This is a little misleading since the ‘Operation’ for the event is ‘UserLoginFailed’ which suggests the login was unsuccessful. We see in the following event the login was eventually successful.
Why are there two ‘Entra ID Sign-In’ events?
- Similar to what was mentioned above, the initial event has the same error code of ‘50199’ but provides a ‘failureReason’ of ‘For security reasons, user confirmation is required for this request. Please repeat the request allowing user interaction.’
Where is the log for the user enumeration query?
- None of the enumeration techniques (users, groups, applications, service principals, and directory roles) produce any events from either source.
After testing a few techniques, I started receiving 429 status code responses for too many requests. There were no logs of this either, unfortunately, as this information could be useful to help identify suspicious activity.

Failed Attempts = Invisible Threats
You’d expect failed attacks to light up your detection and analysis tools, right? Not always.
Take these examples:
Technique: add_mailbox_delegation
Status: 403 Forbidden
Logged? ❌ Nope
msInvader has the technique ‘add_mailbox_delegation’ which can grant full access to another user’s mailbox if the user has the correct permissions. Attempting this action with a user that does not have the required permissions produces a 403 status code (Forbidden) from the API.

No log of this event appears from either source. This appears to be common with other techniques where only the successful attempts make it through to a log.
Technique: read_email, change_user_password
Status: 403 Forbidden
Logged? ❌ Still nothing

Technique: password_spray
Status: 403 Forbidden
Logged? ✅ Yes
Failed login attempts will show up in the logs and msInvader has a ‘password_spray’ technique we can use to show this.

Failed logs:

The reason provided for why the attempts failed:

What can you detect?
Not all hope is lost. Certain actions are reliably logged and can form the basis of effective detection rules. For instance:
Technique: create_rule
Action: Add inbox forwarding rule
Result: 200 OK
Logged? ✅ Yes
A relatively simple action to detect would be for a new inbox forwarding rule added for a user’s mailbox. msInvader has a technique for this.

The Abstract Security platform has content packs containing analytics that can detect this, and other activity, in Microsoft logs.

More complicated analytics can be created that use conditions based on parameters in the requests to Microsoft to make detections more specific and help reduce false positives. For instance, when a mailbox permission is set, the access rights and mailbox folder need to be provided. It’s possible to create analytics to create findings on specific events like setting a user to be ‘Owner’ of another user’s ‘Inbox’ folder.

This produces the finding:

Taking things a step further, we can also add conditions for the grantee receiving the permission. Example finding detecting a user’s ‘Inbox’ folder granting ‘Owner’ access to the ‘Anonymous’ user effectively allowing make anyone an owner without needing credentials:

Detection Is Only As Good As Your Data
Here's the hard truth: many early-stage attack techniques—especially recon and failed modifications—simply don’t generate logs in Microsoft’s default configurations.
Want more visibility? Microsoft offers enhanced logging for Graph API, but it comes with extra costs and some limitations. (ref: https://learn.microsoft.com/en-us/graph/microsoft-graph-activity-logs-overview)
Until then, defenders must focus on:
- Detecting what is logged (e.g., inbox rules, sign-ins, modified permissions)
- Building detections based on attack chains, not just atomic events
- Understanding the environment to uncover misconfigurations
Closing Thoughts
Attackers are getting stealthier and Microsoft’s default logging, while robust in many ways, still has significant blind spots—especially when it comes to enumeration, failed attacks, and misclassified activity.
By understanding what’s logged, what’s not, and how attackers operate within those blind spots, defenders can build more resilient detection strategies.
Stay Curious. Stay Defensive.
Want more research like this? Follow Abstract Security’s CANVAS blog and subscribe to our monthly newsletter.