When a Microsoft 365 account is confirmed compromised, work in three phases: contain (disable the account, revoke its sessions and mark it compromised), remove persistence (rogue MFA methods, app consents, admin roles, mailbox forwarding and inbox rules), then investigate and recover (scope the activity with sign-in logs and Purview Audit, reset the password, re-enable with MFA and lift any sending block). Containment comes first because a password reset alone doesn't end existing sessions, and everything the attacker set up keeps working until you remove it.
Who this is for and what you will have
This runbook is for Microsoft 365 and security administrators who have a confirmed account takeover: a user reports a suspicious MFA prompt they approved, Defender raises an incident, or a partner reports a fraudulent payment request sent from your domain. It follows Microsoft's published order for compromised accounts and adds the commands you need at each step. At the end you will have:
- The attacker locked out of Microsoft Entra ID and every app that relies on it.
- Every known persistence mechanism reviewed and removed.
- A timeline of what the attacker did, which mail they accessed and which files they touched, exported for your records.
- The user back at work with a new password, clean MFA methods and their account marked accordingly in ID Protection.
The response order at a glance
| Phase | Action | Tool | Least privileged role |
|---|---|---|---|
| Contain | Disable the account | Entra admin center, Graph PowerShell | User Administrator (Privileged Authentication Administrator for admin accounts) |
| Contain | Revoke sessions | Entra admin center, Graph PowerShell | Authentication Administrator or User Administrator |
| Contain | Confirm or mark compromised | ID Protection, Defender portal | Security Operator |
| Persistence | Review MFA methods and app passwords | Entra admin center, Graph PowerShell | Authentication Administrator |
| Persistence | Review app consents | Entra admin center, Graph PowerShell | Cloud Application Administrator |
| Persistence | Review forwarding and inbox rules | Exchange Online PowerShell | Exchange recipient management permissions |
| Investigate | Search the audit log | Purview portal, Exchange Online PowerShell | Audit Logs or View-Only Audit Logs |
| Recover | Reset password, re-enable, unblock sending | Entra admin center, Defender portal | User Administrator, Security Administrator |
Keep a written log of each action, who took it and when; you will need it for the investigation timeline.
Prerequisites
- Accounts holding the roles in the table above. If your tenant uses Privileged Identity Management, activate them before you start.
- The Microsoft Graph PowerShell SDK (
Microsoft.Graph.Users,Microsoft.Graph.Users.Actions,Microsoft.Graph.Identity.DirectoryManagement,Microsoft.Graph.Identity.SignIns,Microsoft.Graph.Applications) and the Exchange Online PowerShell module. - For hybrid identities, access to an on-premises Active Directory admin workstation.
- For the Confirm compromised workflow and full risk reports, Microsoft Entra ID P2 or Microsoft Entra Suite. The rest of the runbook works without it.
- Unified audit log ingestion turned on. Check it in Exchange Online PowerShell (not Security & Compliance PowerShell, where the property always shows
False):
Get-AdminAuditLogConfig | Format-List UnifiedAuditLogIngestionEnabledPhase 1: Contain the account
Step 1: Disable the user
Microsoft recommends disabling the compromised account until the investigation is complete. In the Microsoft Entra admin center, go to Entra ID > Users > All users, select the user, select Edit under Account status, clear Account enabled and select Save.
For repeatable or bulk response, use Microsoft Graph PowerShell:
Connect-MgGraph -Scopes "User.ReadWrite.All","Directory.AccessAsUser.All"
$User = Get-MgUser -Search UserPrincipalName:'jason@contoso.com' -ConsistencyLevel eventual
Update-MgUser -UserId $User.Id -AccountEnabled:$falseIf the account is synchronized from on-premises Active Directory, Microsoft's guidance is to disable it there as well and reset the password twice, to reduce the risk of pass-the-hash while replication catches up. Use random values, not the placeholders below:
Disable-ADAccount -Identity jason
Set-ADAccountPassword -Identity jason -Reset -NewPassword (Read-Host -AsSecureString "First random password")
Set-ADAccountPassword -Identity jason -Reset -NewPassword (Read-Host -AsSecureString "Second random password")If the identity is federated, change the password in the on-premises environment.
Step 2: Revoke sessions
Disabling the account blocks new sign-ins, but apps that already hold tokens keep working until those tokens are refused. Revoke the user's refresh tokens and sign-in sessions immediately. In the admin center, open the user's Overview page and select Revoke sessions. In PowerShell:
Connect-MgGraph -Scopes User.RevokeSessions.All
Revoke-MgUserSignInSession -UserId $User.IdUnderstand what this does and doesn't cover:
- Access tokens issued by Microsoft Entra ID last 1 hour by default. An app holding one can keep using it until it expires, unless the app supports continuous access evaluation (CAE), which lets revocation take effect in near real time.
- Browser-based apps often issue their own session cookie after the Entra sign-in. Microsoft Entra ID can't revoke that cookie; the app ends the session when its own token expires or when it learns the account is disabled.
Step 3: Disable compromised devices
If the attacker registered or joined a device to the tenant under this user, or you believe one of the user's devices is compromised, disable the user's registered devices. This requires at least Cloud Device Administrator:
Get-MgUserRegisteredDevice -UserId $User.Id -All | ForEach-Object {
Update-MgDevice -DeviceId $_.Id -AccountEnabled:$false
}This disables every device registered to the user, including their legitimate laptop. Review the list first if you only want to disable the attacker's device.
Step 4: Mark the user as compromised
Marking the account tells ID Protection that the risk is real, which updates the risk state to Confirmed compromised and feeds the detection models. In the Microsoft Entra admin center, go to Protection > Identity Protection > Risky users, select the user and choose Confirm compromised. Security Operator is the least privileged role for this.
If you work from the Microsoft Defender portal, go to Assets > Identities, open the identity and use the Actions menu. Depending on the connectors you have, the actions are Disable, Enable, Revoke session, Mark as compromised and Force password change, and they apply across the accounts Defender correlates to that identity, including on-premises Active Directory when Defender for Identity sensors run on your domain controllers. Track progress under Actions & submissions > Action center.
Phase 2: Remove the attacker's persistence
An attacker who expects to lose the password plants other ways back in. Check each of the following before you re-enable the account.
MFA methods and app passwords
Attackers often register their own phone number or authenticator app. List every method registered to the user:
Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All"
Get-MgUserAuthenticationMethod -UserId jason@contoso.com |
Select-Object Id, @{n='Type';e={$_.AdditionalProperties.'@odata.type'}}In the Microsoft Entra admin center, as at least Authentication Administrator, go to Entra ID > Users, select the user and open Authentication methods. Delete anything the user doesn't recognize, or select Require re-register MFA, which deletes the user's phone numbers, Microsoft Authenticator registrations and software OATH tokens and deactivates hardware OATH tokens, so the user sets up fresh methods at next sign-in.
App passwords aren't revoked by a password reset. Under Entra ID > Users > Multifactor authentication, select the user, choose Manage user settings and check Delete all existing app passwords generated by the selected users.
Application consents
A malicious app that the user consented to keeps its delegated access after a password reset. List the user's delegated permission grants:
Connect-MgGraph -Scopes "Directory.Read.All","DelegatedPermissionGrant.ReadWrite.All"
Get-MgUserOauth2PermissionGrant -UserId $User.Id -All |
Format-List ClientId, ConsentType, ScopeClientId is the object ID of the app's service principal; look it up with Get-MgServicePrincipal -ServicePrincipalId <ClientId>. To remove a grant you don't trust, run Remove-MgOauth2PermissionGrant -OAuth2PermissionGrantId <Id> as at least Cloud Application Administrator. The portal can't revoke grants shown on an app's User consent tab, so use PowerShell or Graph for these. Revoking a grant doesn't stop the user from consenting again; restrict user consent tenant-wide if this was the entry point.
Admin roles
Review the user's Microsoft Entra role assignments, Azure role assignments, and Purview and Defender permissions. Remove any role the user shouldn't hold, and treat a recently added role as evidence: search the audit log for the Add member to role. operation (the trailing period is part of the name).
Mailbox forwarding, inbox rules and delegates
Connect to Exchange Online PowerShell and check SMTP forwarding and inbox rules, including hidden ones:
Get-Mailbox -Identity jason@contoso.com | Format-List Forwarding*Address,DeliverTo*
Get-InboxRule -Mailbox jason@contoso.com -IncludeHidden |
Format-List Name,Enabled,RedirectTo,Forward*,IdentityA nonblank ForwardingSmtpAddress means mail is being forwarded to an external recipient. Look for rules that forward or redirect mail, or move messages into Notes, Junk Email or RSS Subscriptions where the user won't see replies. Remove what the attacker created with Remove-InboxRule and clear forwarding with Set-Mailbox. Also review Full Access and Send As permissions on the mailbox.
Phase 3: Investigate what happened
Start the evidence collection early. Audit (Standard) keeps records for 180 days; users with E5 or the Purview Suite or E5 eDiscovery and Audit add-on get one year for Microsoft Entra ID, Exchange and SharePoint records by default. Anything outside that window is gone.
Sign-in logs
In the Microsoft Entra sign-in logs, filter on the user from just before the first suspicious event and compare IP addresses, locations, times and success or failure. The attacker's IP addresses and the session IDs you find here become filters for every later search. In the Defender portal, the identity page's Timeline tab puts Entra sign-ins, Conditional Access results, Microsoft Graph activity, cloud app events and alerts for that identity on one timeline.
Unified audit log
In the Microsoft Purview portal, open the Audit solution and create a search for the user over the compromise window. Don't filter by activity on the first pass. Date ranges can be at most 180 days, searches keep running after you close the browser, and completed searches are kept for 30 days. Exports are limited to 50,000 rows for Audit (Standard) and 1,000,000 rows for Audit (Premium). Searching requires the Audit Logs or View-Only Audit Logs role.
To script it, use Search-UnifiedAuditLog in Exchange Online PowerShell. By default it returns up to 100 records; use -SessionCommand ReturnLargeSet with a fixed -SessionId and run the command repeatedly to page through up to 50,000 unsorted results:
$start = (Get-Date "2026-10-01 00:00").ToUniversalTime()
$end = (Get-Date).ToUniversalTime()
$ops = "New-InboxRule","Set-InboxRule","UpdateInboxRules","Add-MailboxPermission",
"Send","SendAs","HardDelete","SoftDelete","MoveToDeletedItems",
"FileDownloaded","FileAccessed","Add delegation entry.","Add service principal.",
"Reset user password.","Update user.","Add member to role."
$results = @()
do {
$page = Search-UnifiedAuditLog -StartDate $start -EndDate $end `
-UserIds jason@contoso.com -Operations $ops `
-SessionId "IR-jason" -SessionCommand ReturnLargeSet -ResultSize 5000
$results += $page
} while ($page)
$results | Export-Csv .\IR-jason-audit.csv -NoTypeInformationAdd -IPAddresses with the attacker's addresses to separate their activity from the user's. Exchange admin cmdlets such as Set-Mailbox are recorded under the ExchangeAdmin record type.
Which mail the attacker accessed
The MailItemsAccessed operation is enabled by default for users with Office 365 or Microsoft 365 E3 or E5 licenses and covers POP, IMAP, MAPI, EWS, Exchange ActiveSync and REST access. It records two kinds of access:
- Sync: recorded only for desktop Outlook on Windows or Mac, one record per folder. If a sync record matches the attacker's IP address and client, assume every item in that folder, and potentially the whole mailbox, was downloaded.
- Bind: access to individual messages, aggregated into one record per 2-minute interval, with each message identified by its
InternetMessageId.
Search-UnifiedAuditLog -StartDate $start -EndDate $end -UserIds jason@contoso.com `
-Operations MailItemsAccessed -ResultSize 5000 |
Where-Object { $_.AuditData -like '*"MailAccessType","Value":"Bind"*' }Compare ClientIPAddress, ClientInfoString and SessionId in AuditData against the attacker activity you found in the sign-in logs. The message IDs from bind records tell you exactly which messages to review for sensitive data.
What the attacker sent
Use message trace in the Defender portal for the compromise window and check Sent Items and Deleted Items. Fraudulent payment requests, internal phishing and mass outbound spam all show up here, and internal recipients of phishing from this account need their own follow-up.
Phase 4: Recover the account
When the investigation is complete and every persistence mechanism is gone:
- Reset the password to a strong, unique value. Don't reuse any of the last five passwords, and don't send the new password by email: the attacker may still have a copy of the mailbox. For hybrid users, reset it in Active Directory.
- Re-enable the account (Account enabled in the user's properties, or
Update-MgUser -UserId $User.Id -AccountEnabled:$true). - Have the user register fresh MFA methods, ideally phishing-resistant ones, and make sure a Conditional Access policy requires MFA for them. For the wider pattern of verifying every request instead of trusting the network, see Zero Trust remote access architecture.
- If the mailbox was used to send spam, it's probably on the Restricted entities page in the Defender portal. Remove it there so the user can send again.
- Re-enable any devices you disabled after they've been reimaged or confirmed clean.
Verification
Get-MgUser -UserId jason@contoso.com -Property AccountEnabled,SignInSessionsValidFromDateTime | Format-Listshows the account state and the time sessions were last revoked.Get-MgUserAuthenticationMethodlists only methods the user registered after recovery.Get-MgUserOauth2PermissionGrantno longer lists the removed apps.Get-InboxRule -IncludeHiddenandGet-Mailboxshow no attacker rules or forwarding.- The user's entry under Risky users shows Confirmed compromised or Remediated, and new sign-ins in the sign-in logs come only from expected locations.
Troubleshooting
The attacker still has access after the password reset. Sessions weren't revoked, an app password is still in use, a consented app still holds a grant, or an attacker-registered MFA method lets them pass a reset. Repeat Phase 1 and Phase 2. Remember that a valid access token can last up to an hour for apps that don't support CAE.
Search-UnifiedAuditLog returns exactly 100 results. That's the default limit. Add -SessionCommand ReturnLargeSet and a -SessionId, and keep the same SessionCommand value for the whole session; mixing ReturnLargeSet and ReturnNextPreviewPage on one session limits output to 10,000 results.
The search returns nothing for a single day. If StartDate and EndDate are the same date without a time, the range is zero. Include timestamps, and remember values without a time zone are treated as UTC.
Recent events are missing. Audit records for core services typically become available 60 to 90 minutes after the event, and Microsoft doesn't guarantee a specific time. Run the search again later before concluding the attacker did nothing.
No MailItemsAccessed records. Check that the user is licensed for it (E3 or E5 enables it by default) and that mailbox auditing is on. Absence of sync records doesn't prove no download: an attacker who synced with a client other than desktop Outlook, or worked offline afterwards, leaves less trace.
The user is blocked with error 50053 and "Sign-in was blocked by built-in protections due to high confidence of risk." ID Protection blocked a high-confidence risky sign-in, often from legacy authentication. After the investigation, have the user sign in with a modern client from a known location, or add a known corporate IP to trusted locations.
Closing checklist
- Account disabled (in AD too for hybrid users), sessions revoked, compromised devices disabled.
- User confirmed compromised in ID Protection or marked compromised in Defender.
- Unknown MFA methods removed or re-registration required; app passwords deleted.
- Untrusted OAuth2 permission grants removed; user consent settings reviewed.
- Admin roles reviewed; inbox rules, forwarding and mailbox delegates cleaned up.
- Sign-in logs, audit log and
MailItemsAccessedresults exported for the full window. - Sent mail reviewed with message trace; affected internal and external recipients identified.
- Password reset securely, account re-enabled, MFA re-registered, sending restriction lifted.
- Timeline and actions recorded in your incident log.
References
- Respond to a compromised email account
- Revoke user access in an emergency in Microsoft Entra ID
- Remediate risks and unblock users
- Remediation actions in Microsoft Defender for Identity
- Investigate identities in Microsoft Defender
- Manage authentication methods for Microsoft Entra multifactor authentication
- Review permissions granted to enterprise applications
- Get-MgUserAuthenticationMethod
- Get-MgUserOauth2PermissionGrant
- Use MailItemsAccessed to investigate compromised accounts
- Search the audit log
- Search-UnifiedAuditLog
- Audit log activities
- Manage audit log retention policies