13.3 Mailbox Compromise Assessment

4-6 hours · Module 13

Mailbox Compromise Assessment

Before investigating the fraudulent email, determine whether a.patel’s mailbox is currently compromised. This determines the entire investigation path: compromised mailbox = the attacker operated from inside the organisation. Non-compromised = the attacker spoofed the vendor externally.

Required role: Microsoft Sentinel Reader for KQL queries. Security Reader for sign-in log access.


Step 1: Check for recent suspicious sign-ins

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// a.patel sign-in activity  last 14 days
// Look for: new IPs, non-corporate locations, unusual user agents
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "a.patel@northgateeng.com"
| where ResultType == "0"  // Successful only
| summarize
    SigninCount = count(),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated),
    Apps = make_set(AppDisplayName, 10),
    UserAgents = make_set(tostring(DeviceDetail.browser), 5),
    Location = tostring(any(LocationDetails.countryOrRegion))
    by IPAddress
| order by SigninCount desc

What to examine: Compare the IPs against known corporate IPs (192.0.2.10, 192.0.2.15). Any IP not in the corporate set is suspicious. Cross-reference with the AiTM attacker IPs from Module 12 (203.0.113.47, 203.0.113.52, 203.0.113.89) — if any match, a.patel was re-compromised or the original containment was incomplete.

Verify: If all sign-ins are from known corporate IPs with expected user agents: the mailbox may not be directly compromised. Proceed to email authentication analysis (Step 3) to check for external spoofing. If unknown IPs are present: the mailbox is likely compromised. Proceed to Step 2.


Step 2: Check non-interactive sign-ins for token-based access

1
2
3
4
5
6
7
8
// Non-interactive sign-ins  token replay or API access
AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "a.patel@northgateeng.com"
| where IPAddress !in ("192.0.2.10", "192.0.2.15")
| project TimeGenerated, IPAddress, AppDisplayName,
    ResourceDisplayName, UserAgent = tostring(DeviceDetail.browser)
| order by TimeGenerated desc

What to examine: Non-interactive sign-ins from non-corporate IPs indicate token-based access — the attacker is using a stolen refresh token or an OAuth application to access the mailbox via API. This is the persistence mechanism from Module 12 that may not have been fully eradicated.


Step 3: Analyse the “vendor” email authentication

If a.patel’s mailbox is not compromised, the fraudulent email came from outside. Examine the email headers.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// Authentication details for the vendor bank details email
EmailEvents
| where TimeGenerated between(datetime(2026-03-11T00:00:00Z) .. datetime(2026-03-13T00:00:00Z))
| where RecipientEmailAddress == "a.patel@northgateeng.com"
| where SenderFromAddress has "meridian" or SenderMailFromAddress has "meridian"
| project
    TimeGenerated,
    SenderFromAddress,        // What the user sees
    SenderMailFromAddress,    // Envelope sender
    Subject,
    AuthenticationDetails,    // SPF, DKIM, DMARC
    SenderIPv4,
    ThreatTypes,
    DetectionMethods

What to examine:

Domain comparison. Is the sender domain meridian-precision.co.uk (the real vendor) or meridian-precisi0n.co.uk (lookalike with zero replacing ‘o’)? Lookalike domains are the most common BEC spoofing technique. The difference may be a single character — examine character by character.

Authentication results. If SPF/DKIM/DMARC all pass for the real vendor domain: either Meridian’s email is compromised (vendor-side BEC), or the attacker compromised a.patel’s mailbox and sent the email from within. If SPF/DKIM fail or the domain does not match: external spoofing or lookalike domain.

SenderFromAddress vs SenderMailFromAddress. If these differ: display name spoofing. The user sees “accounts@meridian-precision.co.uk” but the envelope sender is a different domain entirely.


Step 4: Check for inbox rules on a.patel’s mailbox

Regardless of how the attacker sent the email, check for persistence mechanisms.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Inbox rule changes on a.patel's mailbox — last 30 days
CloudAppEvents
| where TimeGenerated > ago(30d)
| where ActionType in ("New-InboxRule", "Set-InboxRule", "Enable-InboxRule")
| extend RuleData = parse_json(RawEventData)
| extend Creator = tostring(RuleData.UserId)
| where Creator == "a.patel@northgateeng.com"
| extend ClientIP = tostring(RuleData.ClientIP)
| extend RuleName = tostring(RuleData.Parameters
    | mv-expand RuleData.Parameters
    | where tostring(RuleData.Parameters.Name) == "Name"
    | project tostring(RuleData.Parameters.Value))
| extend Conditions = tostring(RuleData.Parameters
    | mv-expand RuleData.Parameters
    | where tostring(RuleData.Parameters.Name) in ("SubjectContainsWords", "BodyContainsWords", "FromAddressContainsWords")
    | project tostring(RuleData.Parameters.Value))
| extend ForwardTo = tostring(RuleData.Parameters
    | mv-expand RuleData.Parameters
    | where tostring(RuleData.Parameters.Name) in ("ForwardTo", "RedirectTo")
    | project tostring(RuleData.Parameters.Value))
| extend MoveToFolder = tostring(RuleData.Parameters
    | mv-expand RuleData.Parameters
    | where tostring(RuleData.Parameters.Name) == "MoveToFolder"
    | project tostring(RuleData.Parameters.Value))
| project TimeGenerated, Creator, ClientIP, RuleName,
    Conditions, ForwardTo, MoveToFolder
| order by TimeGenerated asc

BEC-specific inbox rule patterns:

Keyword interception: rules with conditions matching “invoice,” “payment,” “bank,” “account,” “wire,” “transfer,” “meridian.” These rules intercept vendor replies so the legitimate user does not see the real vendor contradicting the fraudulent bank details.

Redirect to hidden folder: rules moving matching emails to RSS Feeds, Conversation History, or a custom folder. The legitimate user never checks these folders.

Forward to external: rules forwarding matching emails to the attacker’s external address for monitoring.

Create a bookmark for each suspicious rule. These are eradication targets (subsection 13.9) and evidence for the IR report.


Step 5: Check for mailbox delegate permissions

The attacker may have granted themselves delegate access rather than using inbox rules.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// Mailbox permission changes  last 30 days
CloudAppEvents
| where TimeGenerated > ago(30d)
| where ActionType in ("Add-MailboxPermission", "Add-RecipientPermission",
    "Set-Mailbox")
| extend Details = parse_json(RawEventData)
| where tostring(Details.ObjectId) has "a.patel"
| extend GrantedTo = tostring(Details.Parameters
    | mv-expand Details.Parameters
    | where tostring(Details.Parameters.Name) == "User"
    | project tostring(Details.Parameters.Value))
| extend AccessRights = tostring(Details.Parameters
    | mv-expand Details.Parameters
    | where tostring(Details.Parameters.Name) == "AccessRights"
    | project tostring(Details.Parameters.Value))
| project TimeGenerated, GrantedTo, AccessRights,
    ClientIP = tostring(Details.ClientIP)

If another user (or a service principal) was granted FullAccess or ReadPermission to a.patel’s mailbox from a non-corporate IP: the attacker has delegate access. This persists independently of a.patel’s password or tokens.


Compile the compromise assessment

QuestionFinding
Is a.patel’s mailbox currently compromised?[Yes/No — from Steps 1-2]
How was the fraudulent email sent?[Compromised mailbox / Spoofed domain / Lookalike domain / Vendor compromised]
Are inbox rules present?[Yes/No — from Step 4. List rules.]
Are delegate permissions present?[Yes/No — from Step 5. List permissions.]

This assessment drives the next subsections: if the mailbox is compromised, containment (12.7) follows the M11 pattern (revoke tokens, reset password). If the email was externally spoofed, containment focuses on email blocking and vendor notification.

Subsection artifact: The 5 compromise assessment queries above. These form the mailbox assessment section of your BEC investigation playbook.


Knowledge check

Check your understanding

1. a.patel's sign-in logs show only corporate IPs. But you find an inbox rule created from IP 203.0.113.52 (a known AiTM attacker IP from Module 12) 3 weeks ago. What does this tell you?

The original AiTM containment in Module 12 was incomplete. The inbox rule was created during the February compromise and was not removed during eradication. The attacker no longer has active sign-in access (no recent suspicious IPs), but the inbox rule persists — it has been silently intercepting payment-related emails for 3 weeks, giving the attacker time to monitor vendor threads and prepare the BEC. Eradication gap from Module 12 enabled this attack.
a.patel created the rule herself
The IP is a false positive
The rule was created by IT during maintenance