Checklist
Compromised mailbox investigation checklist
Based on the article: Investigating a compromised Exchange Online mailbox: rules, forwarding, sign-ins and audit · 5 min read
A user reports that colleagues are receiving strange invoices from them, or you notice a mailbox quietly forwarding everything to an outside address. The next hour matters: attackers who get into a mailbox set up persistence quickly, and the order in which you contain, investigate and recover determines whether they get back in. In this post I'll follow the order Microsoft documents for a compromised cloud mailbox, add the short scripts that check every mailbox rather than just the one reported, and finish with the hardening that makes the next incident smaller.
Before you start
- Exchange Online PowerShell V3 (
Connect-ExchangeOnline) and the Microsoft Graph PowerShell SDK with theUser.ReadWrite.AllandUser.RevokeSessions.Allscopes. - Rights to search the audit log (the Audit Logs or View-Only Audit Logs role in Microsoft Purview) and to read sign-in logs in the Microsoft Entra admin center.
- Know the signs Microsoft lists: the mailbox is blocked from sending, mail goes missing, new inbox rules forward externally or move messages to Notes, Junk Email or RSS Subscriptions, Sent Items contains messages the user never wrote, the GAL entry or signature changed, repeated password resets or lockouts, and newly added external forwarding.
Checklist
- 1
Contain the account
Microsoft's first step is to disable the account for the duration of the investigation; if you can't, reset the password instead. Never send the new password by email, because the attacker may still be reading the mailbox.
powershellConnect-MgGraph -Scopes "User.ReadWrite.All","User.RevokeSessions.All" $user = Get-MgUser -Search "UserPrincipalName:adele@contoso.com" -ConsistencyLevel Eventual Update-MgUser -UserId $user.Id -AccountEnabled:$false Revoke-MgUserSignInSession -UserId adele@contoso.com - 2
Remove the persistence
Next, in Microsoft's order: review the user's registered MFA methods and remove anything you don't recognise; review applications the user consented to and revoke suspicious ones; remove admin roles the account shouldn't hold; then clear mailbox forwarding and rules.
powershellConnect-ExchangeOnline Get-Mailbox -Identity adele@contoso.com | Format-List ForwardingAddress, ForwardingSmtpAddress, DeliverToMailboxAndForward Get-InboxRule -Mailbox adele@contoso.com -IncludeHidden | Format-List Name, Enabled, RedirectTo, ForwardTo, ForwardAsAttachmentTo, DeleteMessage, MoveToFolder, Identity # Clear admin-level forwarding and remove or disable the rule Set-Mailbox -Identity adele@contoso.com -ForwardingAddress $null -ForwardingSmtpAddress $null -DeliverToMailboxAndForward $false Remove-InboxRule -Mailbox adele@contoso.com -Identity "Suspicious Rule Name" Disable-InboxRule -Mailbox adele@contoso.com -Identity "Keep for evidence"The first block lists mailbox-level forwarding; the second lists every rule that forwards, redirects or deletes.
powershellGet-Mailbox -ResultSize Unlimited | Where-Object { $_.ForwardingSmtpAddress -or $_.ForwardingAddress } | Select-Object DisplayName, ForwardingAddress, ForwardingSmtpAddress, DeliverToMailboxAndForward $rules = foreach ($m in Get-Mailbox -ResultSize Unlimited) { Get-InboxRule -Mailbox $m.UserPrincipalName -IncludeHidden -ErrorAction SilentlyContinue | Where-Object { $_.ForwardTo -or $_.RedirectTo -or $_.ForwardAsAttachmentTo -or $_.DeleteMessage } } $rules | Select-Object MailboxOwnerId, Name, Enabled, ForwardTo, RedirectTo, DeleteMessage, MoveToFolder | Export-Csv .\SuspiciousInboxRules.csv -NoTypeInformation - 3
Investigate what happened
Start with Sign-in logs in the Microsoft Entra admin center for the user: look at IP address, location, time, client app and whether each attempt succeeded, and work back to the first unfamiliar success. If you have Microsoft Entra ID P2, the Risky users and Risky sign-ins reports under Identity Protection often already flag the account. Then search the audit log, either in the Microsoft Purview portal (Audit solution) or in PowerShell, starting just before the first suspicious sign-in and without filtering activities at first:
powershellSearch-UnifiedAuditLog -StartDate (Get-Date).AddDays(-14) -EndDate (Get-Date) -UserIds adele@contoso.com ` -SessionCommand ReturnLargeSet -ResultSize 5000 | Export-Csv .\adele-audit.csv -NoTypeInformation Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date) ` -Operations New-InboxRule,Set-InboxRule,Remove-InboxRule,Set-Mailbox -ResultSize 5000 -SessionCommand ReturnLargeSet - 4
Recover and communicate
When the investigation is complete, reset the password again, re-enable the account and register MFA with the user present. If the mailbox was used for spam it will be on the Restricted entities page in the Defender portal (Email & collaboration › Review); remove it there to restore sending.
Verify
- Re-run the forwarding and inbox rule queries for the mailbox and the tenant; they should return nothing unexpected.
- Sign-in logs show only the user's known devices and locations after the reset, and no further risk detections.
- A fresh audit search for
New-InboxRuleandSet-Mailboxreturns only your own remediation entries. - A test message from the mailbox to an external address is delivered, confirming the sending block is lifted.
Tips & gotchas
- Require MFA for everyone and phishing-resistant MFA for admins; the rules and forms persistence techniques only work after credentials are stolen.
- Set Automatic forwarding rules to Off in the default outbound spam policy and grant exceptions by group, so a forwarding rule fails instead of leaking.
- Turn on the default alert policies that matter here under Email & collaboration › Policies & rules › Alert policy: Creation of forwarding/redirect rule, Suspicious email forwarding activity and User restricted from sending email, and send them to a monitored mailbox.
- Confirm auditing is on before you need it:
Get-AdminAuditLogConfig | Format-List UnifiedAuditLogIngestionEnabledin Exchange Online PowerShell should return True. - Keep Outlook current; up-to-date clients block the "start application" rule action by default.
+1 more tips in the full article.