Browse all topics
Microsoft Defender (Security)

Investigating a phishing message that got past defences

By Emil Björk · Microsoft ecosystem consultant, Gothenburg

A runbook for the phish that landed — find every copy, pull it from mailboxes, work out who clicked, submit it so the filters learn, and find out why it got through in the first place.

A user reports a phish. It is in their inbox, it looks convincing, and your first instinct is to delete it and move on. Resist that; the message in front of you is a sample, and the job is to find the population. This runbook assumes Defender for Office 365 — Plan 1 gives you Real-time detections, Plan 2 gives you Threat Explorer and automated investigation. If you only have Exchange Online Protection, the same steps work with message trace and PowerShell, more slowly.

Step 1: get the sample, not a forward

A forwarded phish loses its headers. Get the original via the user's Report button (which lands it in Submissions for you), or from the user's mailbox as an .eml. From the headers you need the sender address, the envelope sender (Return-Path), the sending IP, the subject, the Message-ID, and the timestamp. Paste the headers into the Message Header Analyzer in the Microsoft Remote Connectivity Analyzer if reading them raw is slow.

Note the verdicts Defender already gave: the X-Forefront-Antispam-Report header carries the spam confidence level and the reasons. A phish that arrived with SFV:SKN was allowed by a rule you wrote; SFV:SPM means it was marked spam and the user's junk settings let it through; SFV:NSPM means the filter genuinely thought it was clean. This one header often answers "why did it get through" before you have done anything else.

Step 2: find every copy

Open Threat Explorer (Email & collaboration → Explorer), view All email, and search on the sender address, then on the subject, then on the sending IP, over the last 30 days. Campaigns rotate sender addresses but reuse infrastructure and subjects. Add the URL domain from the message as a filter if it has one — Explorer's URL view also shows you click events, which you will need in step 4.

You should end this step with a list: every recipient, delivery location (Inbox, Junk, Quarantine, Deleted), and whether they clicked. Export it. The Campaigns view in Plan 2 does much of this grouping for you.

Without Defender P1/P2: Get-MessageTrace on sender and subject over 10 days, or the historical trace for older, with Get-MessageTraceDetail for delivery outcome.

Step 3: pull it from mailboxes

From Explorer, select the messages and Take actionSoft delete (recoverable by the user from Deleted Items, which is what you want if you got the verdict wrong) or Hard delete for confirmed malware. This works on messages already read and already moved; it is the same mechanism as zero-hour auto purge (ZAP), just triggered by you.

Actions on more than a handful of messages go through the Action center for approval; if you are the approver, approve them there. Plan 2's automated investigation and response may already have queued the same action from the user's report — check the Action center before duplicating.

Without Defender: New-ComplianceSearch with a KQL query on sender and subject, then New-ComplianceSearchAction -Purge -PurgeType SoftDelete. It is slower and capped per mailbox per run, but it works.

Step 4: who clicked, and what happened next

Explorer's URL view, the Top clicks tab, and UrlClickEvents in advanced hunting show every Safe Links click with its verdict — Allowed, Blocked, Clicked through. Anyone with a click on a credential-harvesting page is a candidate for the compromised account runbook. Check their sign-in logs for the hour after the click, and their audit log for consent grants and inbox rules. If the link led to an OAuth consent page rather than a login form, the account was never compromised in the password sense; look at consents specifically.

If the attachment was the payload, Defender for Endpoint's device timeline for anyone who opened it tells you whether it executed.

Step 5: submit it, and block what needs blocking

Submissions → Submit to Microsoft → the message, marked Should have been blocked. This is not bureaucracy; it feeds the filter and, for a real miss, tends to result in tenant-wide detection within hours. Submit the URL and the attachment separately if the message itself is not the malicious part.

Then decide on blocks in the Tenant Allow/Block List. Block the sender domain if it is attacker-owned; do not block it if it is a compromised legitimate partner — block the specific sender and tell the partner instead. Block the URL if it is not on a shared platform (blocking sharepoint.com because a phish used a SharePoint link will be a short-lived policy). Blocks on files by hash are safe and specific.

Step 6: why did it get through

This is the step that reduces the next one. Work down the list:

  • An allow rule. Transport rules that set SCL to -1, IP allow lists in the connection filter, allowed senders or domains in anti-spam policies, and Tenant Allow entries. SFV:SKN or SFV:SKA in the header points here. Allow lists are the number one reason phish lands in mature tenants — transport rule examples shows the patterns that go wrong.
  • Authentication passed. If SPF, DKIM and DMARC all passed, the message came from where it said — a compromised partner mailbox or a legitimate bulk-mail platform. The fix is with the sender, and your impersonation protection settings decide how much of it you catch anyway.
  • Impersonation settings too narrow. Anti-phishing policy → user and domain impersonation lists. If the phish spoofed your CFO's display name and the CFO was not in the protected list, add the executives and turn on mailbox intelligence.
  • Preset policies not applied. If you are still on a hand-tuned anti-phish policy from 2019, apply the Standard or Strict preset and let Microsoft maintain the thresholds. The anti-spam and anti-phishing guide covers the choice.
  • Safe Links not wrapping, because the policy excluded the recipient or the message was internal. Internal phishing from a compromised colleague bypasses a lot of settings that assume external origin.
  • It was genuinely novel. Sometimes the filter loses. That is what the submission is for.

Close it out

Tell the reporting user thank you, specifically. Users who get thanked report the next one; users who get a lecture stop reporting. Send a short notice to the other recipients if the message was still in inboxes when you pulled it. Record the sender, subject, URL, count delivered, count clicked, and the reason it got through, in whatever your incident log is. Two lines is enough; the trend across a year is the thing worth having.

Further reading

Spot something wrong or want a topic covered? Send it through the contact form.