Detection Engineering • Microsoft 365 • BEC

What Bad Looks Like: Detecting Mailbox Compromise

A practical detection guide for identifying suspicious mailbox access, AitM-related behavior, API-based access patterns, and post-compromise activity in Microsoft 365.

$ hunt-mailbox-compromise --tenant m365-lab
[signal] MFA success followed by unusual mailbox access
[signal] ClientInfoString does not match Outlook or OWA
[alert] MailItemsAccessed spike from unfamiliar context
[next] Correlate sign-ins, mailbox access, and inbox rules
Detection Mindset

Why “bad” matters

Effective detection is not just about matching one event name. It is about understanding how identity, mailbox access, and user behavior change when an account is compromised.

The strongest detections come from chaining signals together: suspicious sign-in context, abnormal mailbox access, and post-compromise behavior.
Visual Detection Flow

Mailbox compromise detection flow

This flow helps turn scattered telemetry into a repeatable investigation path.

1
Identity anomaly appearsSuccessful login from a new IP, unfamiliar location, risky session, or unexpected device context.
2
MFA does not eliminate concernAitM phishing may produce a valid session even when MFA was completed by the user.
3
Mailbox access beginsMailItemsAccessed events increase, especially from a non-standard client or unfamiliar access pattern.
4
Post-compromise behavior followsInbox rules, mailbox changes, message reads, attachment access, or keyword-driven searches appear.
5
Escalate as likely compromiseCorrelated identity + mailbox + behavior anomalies create a high-confidence investigation path.
MFA success + unfamiliar sign-in + mailbox access spike + non-Outlook client is a high-risk chain.
What Bad Looks Like

High-signal scenarios

Mailbox access without Outlook

Mailbox activity appears without normal Outlook, OWA, or mobile client behavior.

MFA success followed by compromise

The user completes MFA, but mailbox activity begins from a suspicious context shortly afterward.

High-volume mailbox reads

Hundreds of messages are accessed in minutes, suggesting automated data mining.

Login to inbox rule creation

A successful sign-in is quickly followed by a new forwarding or hiding rule.

Silent session activity

Mailbox access continues after a single login event without normal interactive behavior.

Client mismatch

The user normally uses Outlook, but activity appears from an unknown or API-like client.

KQL Detection Block

Mailbox access without Outlook client

This hunt looks for mailbox access that does not appear to come from common Outlook, OWA, or mobile clients.

AuditLogs
| where Operation == "MailItemsAccessed"
| where ClientInfoString !has_any ("Outlook", "OWA", "Mobile")
| summarize AccessCount=count() by UserId, ClientInfoString
| where AccessCount > 25
| order by AccessCount desc
Investigate unknown client strings, empty client values, and high-volume access from clients that do not match the user baseline.
KQL Detection Block

High-volume mailbox access

This hunt identifies users with unusually high mailbox read activity in a short window.

AuditLogs
| where Operation == "MailItemsAccessed"
| summarize AccessCount=count() by UserId, bin(TimeGenerated, 30m)
| where AccessCount > 100
| order by AccessCount desc
Tune the threshold based on your environment. Executives, shared mailboxes, and service accounts may need separate baselines.
KQL Detection Block

Login followed by inbox rule creation

This query looks for a successful sign-in followed by inbox rule creation within a short period.

let Signins =
SigninLogs
| where ResultType == 0
| project UserPrincipalName, SigninTime=TimeGenerated, IPAddress, AppDisplayName;

let Rules =
AuditLogs
| where Operation in ("New-InboxRule", "Set-InboxRule", "UpdateInboxRules")
| project UserId, RuleTime=TimeGenerated, Operation, ClientInfoString;

Signins
| join kind=inner Rules on $left.UserPrincipalName == $right.UserId
| where RuleTime between (SigninTime .. SigninTime + 30m)
| project UserPrincipalName, IPAddress, AppDisplayName, Operation, SigninTime, RuleTime, ClientInfoString
| order by RuleTime desc
A new forwarding, deletion, or hiding rule shortly after login is a strong BEC indicator.
KQL Detection Block

MFA success followed by mailbox activity

AitM scenarios can include successful MFA. The concern is what happens immediately after the login.

let MfaSignins =
SigninLogs
| where ResultType == 0
| where AuthenticationRequirement =~ "multiFactorAuthentication"
| project UserPrincipalName, SigninTime=TimeGenerated, IPAddress, AppDisplayName;

let MailboxAccess =
AuditLogs
| where Operation == "MailItemsAccessed"
| project UserId, MailboxTime=TimeGenerated, ClientInfoString;

MfaSignins
| join kind=inner MailboxAccess on $left.UserPrincipalName == $right.UserId
| where MailboxTime between (SigninTime .. SigninTime + 60m)
| summarize MailboxEvents=count(), Clients=make_set(ClientInfoString), IPs=make_set(IPAddress)
  by UserPrincipalName, bin(SigninTime, 1h)
| where MailboxEvents > 50
| order by MailboxEvents desc
MFA completion should not automatically close an investigation. In AitM cases, the attacker may inherit a valid session context.
Investigation Pivots

What to check next

After a mailbox access anomaly, pivot into:

  • Recent sign-ins and IP reputation
  • Authentication method and MFA context
  • Inbox rule creation or modification
  • MailItemsAccessed volume and timing
  • ClientInfoString and app/client changes
Response Actions

Containment mindset

When the pattern looks suspicious, prioritize:

  • Revoke sessions
  • Reset credentials
  • Remove malicious inbox rules
  • Review mailbox forwarding
  • Confirm whether sensitive data was accessed
Final Takeaway

Detection is correlation

Bad activity rarely appears as one perfect alert. It shows up as a chain of behaviors: identity anomalies, suspicious client access, mailbox reads, and post-compromise changes.

Sign-in anomaly + mailbox access + behavior change = high-confidence compromise.

Continue to the EWS Phishing Lab Phase 1 →