Exchange ServerDeep dive

Is my Exchange server compromised? Checking with Microsoft's CSS-Exchange scripts

A structured compromise check for Exchange Server: Health Checker, Test-ProxyLogon, where web shells hide, the logs and Exchange settings attackers abuse, and what to do if you find something.

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 Antivirus
  • Backdoor:ASP/SecChecker.AMicrosoft Defender Antivirus
  • Download failed and temporary fileOABGeneratorLog
  • Trojan:JS/Chopper!dhaMicrosoft Defender detection
How this guide is organised: How it works → Step-by-step → What a clean result looks like → If you find something → Tips & gotchasFlow diagram of the article's sections in reading order: 1. How it works. 2. Step-by-step (6 steps: Preserve evidence first; Run Health Checker on every server; Run Test-ProxyLogon.ps1; Hunt for web shells and tampered URLs; Check Exchange for persistence and data theft; Scan with Microsoft Defender). 3. What a clean result looks like. 4. If you find something. 5. Tips & gotchas. Toolbox: Test-ProxyLogon.ps1, Get-WebGlobalModule, HealthChecker.ps1, AnchorMailbox, ServerInfo~*/*.1How it works2Step-by-step3What a cleanresult looks li…4If you findsomething5Tips & gotchas1Preserveevidence first2Run HealthChecker on e…3RunTest-ProxyLo…4Hunt for webshells and ta…5CheckExchange for…6Scan withMicrosoft Def…TOOLBOXTest-ProxyLogon.ps1Get-WebGlobalModuleHealthChecker.ps1AnchorMailboxServerInfo~*/*How this guide is organised: How it works → Step-by-step → What a clean result looks like → If you find something → Tips & gotchasFlow diagram of the article's sections in reading order: 1. How it works. 2. Step-by-step (6 steps: Preserve evidence first; Run Health Checker on every server; Run Test-ProxyLogon.ps1; Hunt for web shells and tampered URLs; Check Exchange for persistence and data theft; Scan with Microsoft Defender). 3. What a clean result looks like. 4. If you find something. 5. Tips & gotchas. Toolbox: Test-ProxyLogon.ps1, Get-WebGlobalModule, HealthChecker.ps1, AnchorMailbox, ServerInfo~*/*.1How it works2Step-by-step1Preserve evidence first2Run Health Checker on every server3Run Test-ProxyLogon.ps14Hunt for web shells and tampered URLs5Check Exchange for persistence and data theft6Scan with Microsoft Defender3What a clean result looks like4If you find something5Tips & gotchasTOOLBOXTest-ProxyLogon.ps1Get-WebGlobalModuleHealthChecker.ps1AnchorMailboxServerInfo~*/*
At a glance: how this guide is organised · 6 steps · 5 key settings and tools

How it works: what each tool can and can't tell you#

ToolTells youDoesn't tell you
HealthChecker.ps1Whether the server is exposed: build, missing updates, known vulnerabilities, and the state of AMSI, the Emergency Mitigation service (EEMS) and Extended ProtectionWhether anyone exploited it
Test-ProxyLogon.ps1Whether 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 ScannerWhether known web shells and tools are on diskNew or modified malware without a signature
The manual checks belowPersistence and data theft that the scripts don't coverAnything 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#

PowerShell
Get-ExchangeServer | Where-Object { $_.AdminDisplayVersion -match '^Version 15' } |
    ForEach-Object { .\HealthChecker.ps1 -Server $_.Name }
.\HealthChecker.ps1 -BuildHtmlServersReport

Start 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:

PowerShell
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 AnchorMailbox matching ServerInfo~*/*.
  • CVE-2021-26858: Download failed and temporary file in the OABGeneratorLog, which can mean files were written outside the OAB temp folder.
  • CVE-2021-26857: MSExchange Unified Messaging errors containing System.InvalidCastException in the Application log. This check only applies where the Unified Messaging service exists, which rules out Exchange 2019 and SE.
  • CVE-2021-27065: Set-*VirtualDirectory calls in the ECP server logs.
  • Staged data: .zip, .rar and .7z files in C:\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:

PowerShell
$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, FullName

Virtual directory URLs should only ever contain valid URLs, never script. Check them, and search the ECP logs for changes:

PowerShell
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 SilentlyContinue

The 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:

PowerShell
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-TransportAgent

You'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#

PowerShell
Start-MpScan -ScanType FullScan
Get-MpThreatDetection

Microsoft'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#

  1. 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.
  2. Bring in incident response (your security team, a specialist provider or Microsoft) before deleting anything.
  3. 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.
  4. 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.

References#

Written and checked against current Microsoft Learn documentation. Test changes with a pilot group before rolling them out to everyone, and if an admin center path has moved since, search for the setting name instead.

Spotted a mistake, or did this fix work differently for you? Email me or message me on LinkedIn — corrections are credited in the article.

Written by

Omer Eltayeb

Intune Subject Matter Expert in Cairo, Egypt, former Microsoft Cloud Solutions Architect, Microsoft Certified Trainer and Microsoft Innovative Educator Expert (2024–26) and Microsoft Elevate Educator Expert (2026–27). I share practical, step-by-step guides, study plans, scripts and toolkits for Microsoft Intune, Configuration Manager, Microsoft Entra ID, Microsoft Defender, Exchange and Microsoft 365 with the community.

Microsoft Certified Trainer (MCT) 2026Microsoft Innovative Educator Expert 2025–2026Microsoft Elevate Educator Expert 2026–2027ISC2 Certified Information Systems Security Professional (CISSP)Microsoft 365 Certified: Enterprise Administrator Expert (MS-102)