Internet-facing Exchange servers are a favourite target, and the attacks Microsoft has documented follow a familiar pattern: exploit a vulnerability, drop a web shell, then dump credentials or export mailboxes. If you're wondering whether your server has been hit, this post walks through a structured check with Microsoft's CSS-Exchange scripts, the folders and logs worth reading, and what to do if something turns up.
Errors this guide fixes
Exploit:Script/Exmann.A!dhaMicrosoft Defender AntivirusBackdoor:ASP/SecChecker.AMicrosoft Defender AntivirusDownload failed and temporary fileOABGeneratorLogTrojan:JS/Chopper!dhaMicrosoft Defender detection
How it works: what each tool can and can't tell you#
| Tool | Tells you | Doesn't tell you |
|---|---|---|
HealthChecker.ps1 | Whether the server is exposed: build, missing updates, known vulnerabilities, and the state of AMSI, the Emergency Mitigation service (EEMS) and Extended Protection | Whether anyone exploited it |
Test-ProxyLogon.ps1 | Whether the logs show the 2021 ProxyLogon chain (CVE-2021-26855, -26857, -26858 and -27065) | Later vulnerabilities, or attackers using stolen credentials |
| Microsoft Defender Antivirus or Microsoft Safety Scanner | Whether known web shells and tools are on disk | New or modified malware without a signature |
| The manual checks below | Persistence and data theft that the scripts don't cover | Anything older than your logs |
A clean result lowers the odds; it doesn't prove the server is clean. Scale the effort to the exposure: an internet-facing server that missed security updates for months deserves every step below.
Step-by-step#
1. Preserve evidence first#
Logs roll over, and early cleanup destroys the trail. Snapshot the VM or image the disk, then copy %ExchangeInstallPath%Logging\HttpProxy, %ExchangeInstallPath%Logging\ECP, %ExchangeInstallPath%Logging\OABGeneratorLog and the IIS logs under %SystemDrive%\inetpub\logs\LogFiles somewhere safe. If you suspect an active intrusion, involve incident response now.
2. Run Health Checker on every server#
Get-ExchangeServer | Where-Object { $_.AdminDisplayVersion -match '^Version 15' } |
ForEach-Object { .\HealthChecker.ps1 -Server $_.Name }
.\HealthChecker.ps1 -BuildHtmlServersReportStart with the security vulnerability findings: any CVE listed means the server is exposed today, so patch first, and it tells you what an attacker could have used. Exchange 2016 and 2019 have been out of support since 14 October 2025 (see your end-of-support options); the Health Checker guide covers the other findings.
3. Run Test-ProxyLogon.ps1#
Formerly called Test-Hafnium, this script automates the four log checks Microsoft published during the March 2021 attacks. It covers only that chain, and only as far back as your logs go, but it's quick and shows how to read these logs:
Get-ExchangeServer | .\Test-ProxyLogon.ps1 -OutPath $home\desktop\logs
.\Test-ProxyLogon.ps1 -OutPath $home\desktop\logs -CollectFiles # local server, copies flagged logs and files- CVE-2021-26855: HttpProxy log entries with an empty authenticated user and an
AnchorMailboxmatchingServerInfo~*/*. - CVE-2021-26858:
Download failed and temporary filein the OABGeneratorLog, which can mean files were written outside the OAB temp folder. - CVE-2021-26857:
MSExchange Unified Messagingerrors containingSystem.InvalidCastExceptionin the Application log. This check only applies where the Unified Messaging service exists, which rules out Exchange 2019 and SE. - CVE-2021-27065:
Set-*VirtualDirectorycalls in the ECP server logs. - Staged data:
.zip,.rarand.7zfiles inC:\ProgramData. The script can't tell whether an archive belongs to a product, so review each one.
4. Hunt for web shells and tampered URLs#
Microsoft found web shells in C:\inetpub\wwwroot\aspnet_client\ (including system_web\) and in %ExchangeInstallPath%FrontEnd\HttpProxy\owa\auth\, with names such as help.aspx, errorEE.aspx or healthcheck.aspx. List script files there, newest first, and compare with a known-clean server on the same build:
$paths = 'C:\inetpub\wwwroot\aspnet_client', (Join-Path $env:ExchangeInstallPath 'FrontEnd\HttpProxy')
Get-ChildItem -Path $paths -Recurse -File -Include *.aspx, *.ashx, *.asmx |
Sort-Object LastWriteTime -Descending |
Select-Object -First 25 LastWriteTime, Length, FullNameVirtual directory URLs should only ever contain valid URLs, never script. Check them, and search the ECP logs for changes:
Get-OabVirtualDirectory | Format-List Server, InternalUrl, ExternalUrl
Select-String -Path (Join-Path $env:ExchangeInstallPath 'Logging\ECP\Server\*.log') -Pattern 'Set-.+VirtualDirectory'
Get-ChildItem C:\Windows\Temp, C:\root -Filter *.dmp -Recurse -ErrorAction SilentlyContinueThe last line looks for memory dumps in the two folders Microsoft told customers to watch for LSASS dumps. If you find one, treat the credentials of everyone who signed in to that server as stolen.
5. Check Exchange for persistence and data theft#
Attackers have used Exchange's own tools, for example exporting mailbox data with the Exchange PowerShell snap-in. Built-in cmdlets cover the obvious places:
Get-MailboxExportRequest
Get-ManagementRoleAssignment -Role 'Mailbox Import Export' -GetEffectiveUsers
Get-RoleGroupMember 'Organization Management'
Search-AdminAuditLog -StartDate (Get-Date).AddDays(-90) -Cmdlets New-MailboxExportRequest, New-ManagementRoleAssignment, Add-RoleGroupMember
Get-TransportRule | Format-Table Name, State, Priority
Get-TransportAgentYou're looking for export requests nobody asked for, new role assignments or group members, transport rules that copy or redirect mail, and transport agents you don't recognise. On the Windows side, review local administrators, scheduled tasks, services and the IIS native modules (Get-WebGlobalModule).
6. Scan with Microsoft Defender#
Start-MpScan -ScanType FullScan
Get-MpThreatDetectionMicrosoft's detections for the 2021 web shells included Exploit:Script/Exmann.A!dha and Backdoor:ASP/SecChecker.A, plus generic ones such as Trojan:JS/Chopper!dha. The documented Exchange antivirus exclusions don't cover the web-facing folders above, so a full scan does look there. Microsoft Safety Scanner gives a standalone second opinion, and servers onboarded to Microsoft Defender for Endpoint also have alerts and a device timeline in the Microsoft Defender portal.
What a clean result looks like#
- Health Checker lists no vulnerabilities, and AMSI, EEMS and Extended Protection are in the state you expect.
- Test-ProxyLogon reports no hits, or only hits you can explain.
- No unexplained script files, no script in virtual directory URLs, no dumps or staged archives.
- No unexpected export requests, role changes, transport rules or agents, and no Defender detections.
That's reassurance, not proof, especially if logs from the exposure window are gone.
If you find something#
- Treat it as a security incident. Cut the server off from the internet (publishing rule or firewall), but keep it running until evidence has been captured.
- Bring in incident response (your security team, a specialist provider or Microsoft) before deleting anything.
- Assume the credentials used on the server are exposed and reset them, starting with administrators and service accounts. Exchange servers hold extensive Active Directory permissions, so scope the investigation beyond Exchange.
- Rebuild rather than clean: deleting a web shell doesn't remove other persistence. Bring up a clean server on the latest Exchange Server SE build and security update, then harden it with Extended Protection, EEMS and AMSI and a routine for security updates.
Tips & gotchas#
- Check every Exchange server, not only the internet-facing ones; attackers move laterally.
- Logs are your evidence. Forward Exchange, IIS and Windows logs to a SIEM, or keep them long enough to cover a realistic exposure window.
- Use current tools from the source. Download scripts from the CSS-Exchange site or its GitHub releases; vulnerability-specific scripts are retired over time, so check the repository's Security folder, not an old blog post.

