How to Investigate a Compromised Exchange Server: A Practical Incident Response Checklist (Exchange 2016/2019)
When an Exchange server is suspected of being compromised, the first hour matters more than almost anything else you’ll do in the investigation, and it’s also when it’s easiest to make a mistake that destroys evidence or lets the attacker maintain access while you’re still figuring out what happened. This is a practical checklist to work through, in order, on Exchange 2016/2019.
1. Don’t reboot, don’t “clean up” yet
The instinct to restart the service or delete a suspicious file immediately is understandable and almost always wrong at this stage. A reboot clears volatile memory (active connections, in-memory web shells, running malicious processes) that you may never get evidence of again. Isolate network access first if containment is urgent, and don’t destroy the box.
2. Check for known Exchange web shell locations first
These are the paths attackers overwhelmingly use, and checking them takes two minutes:
Get-ChildItem -Recurse -Include *.aspx "$env:ExchangeInstallPath\FrontEnd\HttpProxy" | Sort-Object LastWriteTime -Descending | Select-Object -First 20
Get-ChildItem -Recurse -Include *.aspx "$env:ExchangeInstallPath\ClientAccess" | Sort-Object LastWriteTime -Descending | Select-Object -First 20
Look specifically for .aspx files with recent write timestamps that don’t match a patch/update window, unusually small file sizes (a web shell is often a few lines), or filenames that don’t match Microsoft’s normal naming (real Exchange .aspx files follow predictable patterns, so anything that looks hand-named is worth immediate attention).
3. Pull IIS logs for the actual exploitation window
Get-ChildItem "C:\inetpub\logs\LogFiles\W3SVC1" | Sort-Object LastWriteTime -Descending | Select-Object -First 5
Select-String -Path "C:\inetpub\logs\LogFiles\W3SVC1\*.log" -Pattern "autodiscover.json","X-AnonResource","X-BEResource" | Select-Object -First 50
Those specific strings are the well-documented indicators from the ProxyShell/ProxyLogon-family exploitation chains: a genuine POST to an autodiscover endpoint with those headers from an external IP, followed shortly by a new .aspx file appearing, is close to a smoking gun.
4. Check for newly created mailbox export requests and mailbox permissions
A very common post-compromise action is granting a hidden mailbox export or full-access permission for data exfiltration:
Get-MailboxExportRequest
Get-MailboxPermission -Identity * | Where-Object { $_.User -notlike "NT AUTHORITY\SELF" -and $_.IsInherited -eq $false }
Get-Mailbox | Get-MailboxPermission | Where-Object { $_.AccessRights -like "*FullAccess*" -and $_.User -notlike "NT AUTHORITY*" }
Any export request or full-access grant you don’t recognize, especially against high-value mailboxes (executives, IT admins, finance), needs to be traced to who or what created it and when.
5. Check for new or modified transport rules and mail flow rules
A well-known persistence/exfiltration technique is a transport rule silently BCC-ing or forwarding specific mail externally:
Get-TransportRule | Select-Object Name,State,WhenChanged,Description | Sort-Object WhenChanged -Descending
Get-Mailbox -ResultSize Unlimited | Get-InboxRule | Where-Object { $_.ForwardTo -ne $null -or $_.RedirectTo -ne $null }
Check both the org-wide transport rules and individual mailbox inbox rules. Attackers frequently set a quiet forwarding rule on one compromised mailbox rather than touching org-wide config, since it’s far less likely to be noticed.
6. Check for new admin accounts and role group membership changes
Get-RoleGroupMember "Organization Management"
Get-ManagementRoleAssignment -RoleAssignee "Organization Management"
Get-EventLog -LogName Security -InstanceId 4728,4732,4756 -After (Get-Date).AddDays(-14)
Event IDs 4728/4732/4756 are “member added to a security-enabled group” (global/local/universal respectively). Cross-reference any hits against your own known change requests.
7. Check certificate bindings
Less common but seen in the wild: an attacker installing a rogue certificate to intercept/decrypt traffic. Confirm every bound certificate is one you actually issued or purchased:
Get-ExchangeCertificate | Format-List Subject,Thumbprint,NotAfter,Services,Issuer
What to preserve before you remediate
Once you’ve found something, resist immediately deleting it. At minimum, export the suspicious file(s), the relevant IIS log date range, and the output of every command above to a location off the affected server, before you patch, isolate, or clean anything. You’ll want this if you ever need to determine scope (what data was actually accessed) or report the incident.
Frequently asked questions
Is Exchange 2016/2019 still a common target?
Yes, internet-facing Exchange servers remain one of the most consistently targeted pieces of infrastructure precisely because of how much access a compromised Exchange server grants (mailbox data, and often a path toward broader Active Directory compromise via Exchange’s traditionally broad AD permissions).
Should I involve law enforcement or a forensics firm?
If you find evidence of actual data exfiltration (not just an attempted/blocked exploit), that’s generally the point to loop in your legal/compliance team, who can make the call on formal incident response and disclosure obligations. This checklist is for the technical triage that happens before that conversation, not a replacement for it.
