
إثبات مفهوم تعليمي لثغرة PrintNightmare (CVE-2021-1675/34527) مع حمولة محاكاة غير وظيفية، وتحليل تدفق الهجوم، وربط MITRE، وإرشادات الكشف، وخطوات المعالجة.
النوع: إثبات المفهوم — محاكاة (غير وظيفية) CVE: CVE-2021-1675 + CVE-2021-34527 CVSS: 7.8 (LPE) / 8.8 (RCE) الاسم المستعار: PrintNightmare تم التصحيح: يونيو/يوليو 2021 — KB5004945 أُضيف إلى CISA KEV: يوليو 2021
⚠️ الحمولة الخاصة بإثبات المفهوم هذا خيالية بشكل صريح وغير ضارة — فقط 4 بايتات من ترويسة DCE/RPC متبوعة باسم الدالة بنظام ASCII. لا تنفذ كودًا، ولا تثبّت برنامج تشغيل، ولا ترفع الامتيازات. الاستخدام حصريًا لأغراض التعلم وتطوير أنظمة الكشف.
Developed by: HKK$ cat ./vulnerability_summary.txtCVE-2021-1675، المعروف باسم PrintNightmare، هو ثغرة أمنية حرجة لتنفيذ التعليمات البرمجية عن بُعد ورفع الامتيازات المحلية في خدمة Windows Print Spooler. تسمح هذه الثغرة للمهاجمين بتنفيذ تعليمات برمجية عشوائية بامتيازات SYSTEM من خلال استغلال الدالة RpcAddPrinterDriverEx()، المستخدمة للتثبيت عن بُعد لبرامج تشغيل الطابعات دون التحقق المناسب من التحكم في الوصول.
صُنّفت في الأصل على أنها LPE (CVSS 7.8) وتم تصحيحها في تحديث Patch Tuesday لشهر يونيو 2021، ثم أعادت Microsoft تصنيف الثغرة على أنها RCE (CVSS 8.8) في 21 يونيو. لتجنب الالتباس، حصل ناقل RCE على معرّف جديد، CVE-2021-34527 — وكلاهما يُشار إليهما عادةً باسم PrintNightmare.
$ cat ./timeline.txtJun 08, 2021 Microsoft تنشر التصحيح الأولي في Patch Tuesday — CVE-2021-1675 (LPE, CVSS 7.8)
Jun 21, 2021 Microsoft تعيد التصنيف كـ RCE (CVSS 8.8)
Jun 29, 2021 باحثون ينشرون PoC عن طريق الخطأ — معتقدين أنها نفس الثغرة التي تم تصحيحها بالفعل
Jul 01, 2021 تم تخصيص CVE-2021-34527 لناقل RCE — المتميز عن LPE الأصلي
Jul 02, 2021 Microsoft تطلق تصحيحًا طارئًا خارج النطاق: KB5004945
Jul 2021 CISA تضيف إلى كتالوج الثغرات المستغلة المعروفة
استغلال نشط من قبل مجموعات برامج الفدية (Vice Society, Magniber, إلخ.)
$ cat ./architecture.txt┌──────────────────────────────────────────────────────────────────────────┐
│ PRINTNIGHTMARE — ATTACK FLOW │
│ │
│ المهاجم (مستخدم مصادق) WINDOWS PRINT SPOOLER │
│ (spoolsv.exe) │
│ 1. المصادقة بأي حساب ┌────────────────────────────┐ │
│ نطاق صالح │ يعمل كـ SYSTEM │ │
│ │ │ نشط افتراضيًا على جميع │ │
│ 2. الاتصال عبر RPC إلى │ أنظمة Windows، بما فيها │ │
│ named pipe \pipe\spoolss │ وحدات التحكم بالمجال DCs │ │
│ │ └──────────────┬─────────────┘ │
│ │ │ │
│ 3. استدعاء RpcAddPrinterDriverEx() │ │
│ مع مسار إلى DLL خبيثة ────────────────────────────────►│ │
│ (UNC: \\attacker\share\evil.dll) │ │
│ ┌────────────▼────────────┐ │
│ │ Print Spooler يقوم بتحميل│ │
│ │ برنامج التشغيل (DLL) │ │
│ │ كـ SYSTEM دون التحقق من │ │
│ │ المصدر أو السلامة │ │
│ └────────────┬────────────┘ │
│ │ │
│ ◄── RCE / LPE كـ SYSTEM ──────────────────────────────┘ │
│ مستخدم إداري جديد، reverse shell، │
│ نشر برامج فدية، إلخ. │
│ │
│ ───────────────────────────────────────────────────────────────────── │
│ إثبات المفهوم هذا: فقط اتصال TCP + 25 بايت → بدون RPC حقيقي → بدون استغلال │
└──────────────────────────────────────────────────────────────────────────┘
$ cat ./design_decisions.mdfake_rpc_payload = b"\x05\x00\x0b\x03RpcAddPrinterDriverEx"
هذه الحمولة يبلغ حجمها 25 بايت وتوضح مفهومين في وقت واحد:
البايتات 0-3: ترويسة DCE/RPC شرعية
البايتات 4-24: اسم الدالة بنظام ASCII
RpcAddPrinterDriverEx — اسم الدالة الثغرة، كنص عادي.
لماذا لا تعمل هذه الحمولة كاستغلال حقيقي؟
إن BIND RPC شرعي يتطلب، بعد ترويسة الـ 4 بايتات:
- max_xmit_frag (2 بايت)
- max_recv_frag (2 بايت)
- assoc_group_id (4 بايت)
- num_ctx_items (1 بايت)
- context_elem[] → Interface UUID الخاص بـ MS-RPRN:
{12345678-1234-ABCD-EF00-0123456789AB}
- transfer_syntaxes → NDR UUID
بدون هذا الهيكل، يرفض Windows الحزمة فورًا. الحمولة، في الواقع، هي مجرد تأكيد على الاتصال — "هل يمكنني الوصول إلى المنفذ 445 بهذه الحمولة الوهمية؟".
sock.connect((target_ip, 445))
لماذا 445 وليس 135 (RPC Endpoint Mapper)؟
يستخدم PrintNightmare SMB named pipe \pipe\spoolss كناقل — وليس RPC المباشر. التدفق الحقيقي هو:
1. اتصال TCP → المنفذ 445 (SMB)
2. مفاوضات SMB + إعداد الجلسة (مصادقة NTLM/Kerberos)
3. اتصال الشجرة → IPC$
4. فتح named pipe → \pipe\spoolss
5. DCE/RPC BIND → واجهة MS-RPRN
6. استدعاء RpcAddPrinterDriverEx() مع NDR marshaling
يحاكي إثبات المفهوم الخطوة 1 فقط — اتصال TCP الأولي — دون تنفيذ الخطوات 2-6.
sock.settimeout(5): مهلة 5 ثوانٍ تمنع إثبات المفهوم من التعليق على المضيفين الذين لا يستجيبون. مفيد للمسح السريع لتوفر المنفذ.
السبب الجذري في كلاهما هو نفسه: الدالة RpcAddPrinterDriverEx() تفشل في التحقق من مصدر ملفات برامج التشغيل، ولا تفرض قيود امتياز مناسبة لتثبيت برامج التشغيل، ولا تتحقق من صحة أو سلامة ملفات DLL التي يتم تحميلها.
$ cat ./mitre_mapping.ymltactic: Initial Access / Lateral Movement
- T1210 # Exploitation of Remote Services
# استدعاء RPC عبر \pipe\spoolss لمضيف بعيد
# يتطلب بيانات اعتماد نطاق صالحة
tactic: Privilege Escalation
- T1068 # Exploitation for Privilege Escalation
# مستخدم عادي → SYSTEM عبر Print Spooler
# CVE-2021-1675 (LPE): عملية محلية ترفع إلى SYSTEM
tactic: Execution
- T1569.002 # System Services: Service Execution
# DLL خبيثة يتم تحميلها بواسطة spoolsv.exe كـ SYSTEM
# يعادل تنفيذ كود عبر خدمة Windows
- T1055 # Process Injection
# DLL محقونة في سياق عملية spoolsv.exe (SYSTEM)
tactic: Persistence
- T1547.012 # Boot or Logon Autostart: Print Processors
# برنامج التشغيل المسجل يستمر بين عمليات إعادة التشغيل
# مخزن في: HKLM\SYSTEM\CurrentControlSet\Control\Print\
tactic: Defense Evasion
- T1036.005 # Masquerading: Match Legitimate Name or Location
# DLL خبيثة مسماة كبرنامج تشغيل شرعي (مثال: Canon_XP.dll)
$ cat ./detection_opportunities.md# Event ID 808 — فشل Print Spooler في تحميل DLL مشبوهة
# المصدر: Microsoft-Windows-PrintService/Admin
الشرط:
EventID: 808
Log: Microsoft-Windows-PrintService/Admin
Level: Error
Description CONTAINS: "failed to load a plug-in module"
دليل حقيقي (لوحظ في البرية):
"The print spooler failed to load a plug-in module
C:\Windows\system32\spool\DRIVERS\x64\3\svch0st.dll"
# Typosquatting لـ svchost.dll → DLL خبيثة
# Event ID 316 — برنامج تشغيل مثبت عبر RpcAddPrinterDriverEx
# المصدر: Microsoft-Windows-PrintService/Admin
الشرط:
EventID: 316
Log: Microsoft-Windows-PrintService/Admin
Message CONTAINS: "RpcAddPrinterDriverEx"
OR
Message CONTAINS: "\\\\*\\*" # مسار UNC → DLL عن بُعد
# عملية فرعية مشبوهة من Print Spooler
EventID: 1 (Process Creation)
الشرط:
ParentImage: C:\Windows\System32\spoolsv.exe
Image: cmd.exe أو powershell.exe أو wscript.exe أو mshta.exe
الخطورة: حرجة — لا يجب أن يطلق spoolsv قذائف
# DLL محملة من مسار غير قياسي
EventID: 7 (Image Loaded)
الشرط:
Image: C:\Windows\System32\spoolsv.exe
ImageLoaded NOT STARTS WITH:
- C:\Windows\System32\spool\DRIVERS\
- C:\Windows\System32\
- C:\Windows\SysWOW64\
الخطورة: عالية
للكشف على مستوى الشبكة، راقب named pipes الخاصة بـ SMB: وجود \pipe\spoolss مقترنًا بعمليات RpcEnumPrinterDrivers أو RpcAddPrinterDriverEx هي مؤشرات مباشرة على استغلال PrintNightmare.
# قاعدة Zeek / Suricata مفاهيمية:
alert smb any any -> $SERVERS 445 (
msg:"PrintNightmare RpcAddPrinterDriverEx via SMB";
content:"|5c 70 69 70 65 5c 73 70 6f 6f 6c 73 73|"; # \pipe\spoolss
content:"RpcAddPrinterDriverEx";
sid:2021001675;
)
$ cat ./remediation.mdالخيار 1 — تعطيل Print Spooler (إذا لم تكن الطباعة ضرورية)
PowerShell:
Stop-Service -Name Spooler -Force
Set-Service -Name Spooler -StartupType Disabled
الخيار 2 — حظر الطباعة عن بُعد عبر Group Policy
Computer Configuration → Administrative Templates → Printers
→ "Allow Print Spooler to accept client connections": DISABLED
هذا يعطل الناقل البعيد فقط، مع الحفاظ على الطباعة المحلية
الخيار 3 — تطبيق التصحيحات (إلزامي بغض النظر عن الخيارات أعلاه)
KB5004945 → تصحيح خارج النطاق يوليو 2021
+ التصحيحات التراكمية اللاحقة
التحقق بعد التصحيح — السجل قد يترك النظام ثغرة:
REG QUERY "HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
إذا كان NoWarningNoElevationOnInstall=1 أو UpdatePromptSettings=0 → لا يزال ثغرة
الإصلاح: تعيين كلا القيمتين إلى 0 أو إزالة المفاتيح
أولوية خاصة: وحدات تحكم المجال DCs
وحدات DC تشغل Print Spooler افتراضيًا
اختراق DC عبر PrintNightmare = اختراق كامل لمجال AD
$ cat ./usage.sh# تثبيت التبعية (socket هي مكتبة قياسية)
python --version # Python 3.x، بدون الحاجة إلى pip
# تعديل IP الهدف في السكربت (فقط في مختبر مصرح به)
# simulate_printnightmare_attack("192.168.1.xxx")
python poc_cve_2021_1675.py
# الإخراج المتوقع إذا كان المنفذ 445 متاحًا:
[+] Payload enviado para 192.168.1.117
# الإخراج المتوقع إذا كان المنفذ مغلقًا/مفلترًا:
[-] Erro ao conectar: [Errno 111] Connection refused
# أو
[-] Erro ao conectar: timed out
ماذا يشير هذا الإخراج: فقط أن المنفذ 445 متاح. لا يؤكد وجود ثغرة — لذلك، سيكون من الضروري إجراء RPC BIND حقيقي + التحقق من إصدار التصحيح.
$ cat ./poc_vs_real_exploit.mdمقارنة صريحة بين إثبات المفهوم المحاكى والاستغلال الحقيقي.
$ cat ./lessons_learned.txt[+] Print Spooler النشط على وحدات DC افتراضيًا هو السيناريو الأكثر حرجًا — SYSTEM على DC = نهاية اللعبة
[+] SMB named pipes كناقل RPC هي ناقل غير مقدر في الدفاعات الموجهة للمحيط
[+] DCE/RPC بروتوكول معقد — فهم بنية bind/call يساعد في إنشاء التوقيعات
[+] CVE المنشورة ≠ التصحيح المطبق — بعد أسابيع من التصحيح، كانت معظم البيئات لا تزال ثغرة
[+] مفاتيح سجل PointAndPrint يمكنها إعادة إدخال الثغرة حتى بعد التصحيح — التحكم بعد التصحيح أمر بالغ الأهمية
[-] إثبات المفهوم هذا يتحقق فقط من اتصال TCP — لا يتحقق مما إذا كان النظام مصححًا بالفعل
[-] مقبس نقي بدون SMB لا يمكنه التفاوض على المصادقة — قيد أساسي في النهج
[-] settimeout(5) قد ينتج نتيجة سلبية خاطئة على الشبكات البطيئة — فكر في مهلة قابلة للتخصيص
[→] التحسينات: استخدام impacket لـ RPC حقيقي، والتحقق من لافتة SMB لبصمة إصدار نظام التشغيل،
واختبار KB المطبق عبر استعلام سجل عن بُعد
CVE Research · PrintNightmare · Patched July 2021 · CISA KEV · Simulated payload only
| البايت | القيمة | المعنى |
|---|
\x05 | 5 | إصدار بروتوكول DCE/RPC (الإصدار 5 — معيار Windows) |
\x00 | 0 | الإصدار الفرعي 0 |
\x0b | 11 | نوع PDU: BIND — الخطوة الأولى في مفاوضات RPC |
\x03 | 3 | الأعلام: `PFC_FIRST_FRAG(0x01) |
| الجانب | CVE-2021-1675 | CVE-2021-34527 |
|---|
| الناقل | محلي (LPE) | عن بُعد (RCE) |
| CVSS | 7.8 | 8.8 |
| المصادقة | حساب محلي | حساب نطاق مصادق |
| التصحيح | يونيو 2021 (Patch Tuesday) | يوليو 2021 (خارج النطاق KB5004945) |
| الدالة الثغرة | RpcAddPrinterDriverEx | RpcAddPrinterDriverEx |
| السيناريو | رفع محلي | RCE عن بُعد عبر SMB named pipe |
| المكوّن | إثبات المفهوم هذا | استغلال حقيقي |
|---|
| الاتصال | مقبس TCP على المنفذ 445 | جلسة SMB + اتصال شجرة IPC$ |
| المصادقة | لا شيء | NTLM أو Kerberos (حساب نطاق) |
| Named pipe | غير منفذ | \pipe\spoolss |
| RPC BIND | مزيف (4 بايتات + ASCII) | DCE/RPC BIND مع UUID لـ MS-RPRN |
| الدالة المستدعاة | غير مستدعاة | RpcAddPrinterDriverEx() عبر NDR |
| مسار DLL | غير مرسل | UNC: \\attacker\share\evil.dll |
| النتيجة | طباعة في وحدة التحكم | RCE كـ SYSTEM / LPE |
| الكشف | شبه معدوم | EventID 808, 316, Sysmon 1/7 |