
إثبات مفهوم لاستغلال CVE-2026-41651، وهو تصعيد صلاحيات محلي من نوع TOCTOU في PackageKit، مع تحليل تقني ومنطق كشف وإرشادات معالجة.
التصنيف: أداة تقييم الفريق الأرجواني
للاستخدام المصرح به فقط. هذه الوثيقة والبرنامج النصي للاختبار المرفق مخصصان حصريًا للتحقق الأمني الداخلي على الأنظمة التي تم الحصول على إذن كتابي لها.

| الحقل | القيمة |
|---|---|
| معرف CVE | CVE-2026-41651 |
| CWE | CWE-367 — سباق التحقق من الوقت مقابل وقت الاستخدام (TOCTOU) |
| المكوّن | PackageKit (packagekitd, خدمة D-Bus) |
| المتأثر | PackageKit ≤ 1.3.4 |
| تم الإصلاح في | PackageKit 1.3.5 |
| الأثر | تصعيد الامتيازات المحلي → الجذر |
| ناقل الهجوم | محلي / D-Bus (جلسة مستخدم غير مميز) |
| تم الكشف | 2026-04-22 (فريق الاختراق الأحمر لـ Deutsche Telekom) |
| النشرة | GHSA-f55j-vvr9-69xv |
| التزام الإصلاح | 76cfb675fb31acc3ad5595d4380bfff56d2a8697 |
PackageKit هي طبقة تجريد D-Bus لإدارة حزم النظام، وهي موجودة افتراضيًا على أجهزة سطح المكتب القائمة على GNOME عبر Debian وUbuntu وFedora وRHEL وSUSE وArch Linux. نظرًا لأنها تتوسط عمليات الحزم المميزة نيابة عن المستخدمين غير المميزين، فإن وجود خلل في تدفق التفويض الخاص بها له تأثير جذري على مستوى النظام بأكمله.
pk-transaction.c (قبل الإصدار 1.3.5) لم يفرض حارس حالة على إعادة استدعاء طرق الإجراء. يمكن لعميل D-Bus استدعاء InstallFiles (أو طرق إجراء أخرى) عدة مرات على نفس كائن المعاملة بعد أن انتقل بالفعل خارج PK_TRANSACTION_STATE_NEW.
المهاجم (غير مميز)
│
├─① CreateTransaction() → PackageKit يُرجع مسار كائن المعاملة (tid)
│
├─② InstallFiles(tid, FLAG_SIMULATE=4, [dummy.pkg])
│ PackageKit يضع فحص تفويض polkit في قائمة الانتظار لـ dummy.pkg.
│ لا يحدث أي تثبيت بعد — SIMULATE تعني تشغيل تجريبي فقط.
│
├─③ InstallFiles(tid, FLAG_NONE=0, [payload.pkg]) ← نافذة TOCTOU
│ إعادة استدعاء على نفس tid قبل اكتمال التفويض.
│ الإصدارات المعرضة تستبدل المعاملات في قائمة الانتظار بـ payload.pkg.
│
└─④ polkit يمنح التفويض (وافق المستخدم أو تفويض تلقائي)
packagekitd يثبّت payload.pkg كجذر.
سكربت postinst/post الخاص بالحزمة: install -m 4755 /bin/bash /tmp/.suid_bash
المهاجم ينفذ /tmp/.suid_bash -p → قشرة جذر.
الخطوتان ② و③ تُرسلان كاستدعاءات D-Bus غير متزامنة غير محظورة على نفس الاتصال وتُفرَّغان في كتابة واحدة. تصل الرسالتان إلى packagekitd قبل أن يتمكن من معالجة ② وتقديم آلة الحالة، مما يترك نافذة TOCTOU مفتوحة. يضيف الإصلاح في 1.3.5 فحص حالة صريحًا يُرجع PK_TRANSACTION_ERROR_INVALID_STATE على أي إعادة استدعاء بعد PK_TRANSACTION_STATE_NEW.
الملف: cve-2026-41651-purpleteam.py
اللغة: Python 3
التبعيات: python3-gi (ربط GObject introspection / GLib/Gio)
يوضح قابلية استغلال CVE-2026-41651 على نظام اختبار مُجهّز لأغراض:
| المرحلة | الإجراء |
|---|---|
| الإعداد | يفحص /proc/mounts لاختيار دليل إسقاط SUID/قابل للتنفيذ، ويضبط umask(022)، ويطبق chmod صريحًا على جميع مخرجات البناء، ثم يبني حزمة وهمية وحزمة حمولة في /tmp |
| الاستغلال | يفتح اتصال D-Bus للنظام، وينشئ معاملة PackageKit، ويطلق سباق الاستدعاءين |
| الحمولة | سكربت ما بعد التثبيت في الحزمة ينسخ /bin/bash إلى <drop_dir>/.suid_bash بالوضع 04755، المالك root. يتم تحديد دليل الإسقاط في وقت التشغيل (انظر دعم البيئات المحصّنة) |
| التصعيد | يتحقق من وجود ثنائي SUID (مهلة 90 ثانية)، ثم ينفذ execl عليه مع -p للحصول على قشرة جذر |
| التنظيف | يزيل ملفات .deb/.rpm المؤقتة عند الخروج (نجاحًا أو فشلًا) |
يمكن للأنظمة المحصّنة افتراضيًا حظر الاستغلال عند نقطتين مستقلتين. يتعامل البرنامج النصي مع كلتيهما تلقائيًا.
027 / 077)يؤدي umask الموروث من العملية بقيمة 027 أو 077 إلى إنتاج mkdir() لأدلة 750 أو 700. يجب على كل من dpkg-deb وrpmbuild اجتياز شجرة البناء الكاملة — إذا كان أي دليل غير قابل للقراءة يفشل البناء بصمت.
الإصلاح المطبق: يتم استدعاء os.umask(0o022) عند بدء التشغيل قبل إنشاء أي ملف أو دليل. بالإضافة إلى ذلك، يتلقى كل دليل وملف في شجرة البناء chmod صريحًا فور الإنشاء (0o755 للأدلة والسكربتات، 0o644 لملفات البيانات)، بحيث تكون الأذونات الصحيحة مضمونة بغض النظر عن umask الموروث.
nosuid / noexec على /tmp| العلم | التأثير على الاستغلال |
|---|---|
nosuid | النواة تزيل بصمت بت SUID من أي ملف مخزن على نظام الملفات هذا — bash المنسوخ لا يصبح جذرًا أبدًا |
noexec | لا يمكن تنفيذ ثنائي SUID على الإطلاق |
الإصلاح المطبق: عند بدء التشغيل، يقرأ _find_suid_dir() ملف /proc/mounts ويختبر الأدلة المرشحة بترتيب الأفضلية حتى يجد نظام ملفات لا يحتوي على أي من العلمين. يتم بعد ذلك دمج المسار المُحل في سكربت ما بعد التثبيت للحمولة ويُستخدم للتحقق والتنفيذ.
| الأولوية | المرشح | التحصين النموذجي |
|---|---|---|
| 1 | /var/tmp | نادرًا ما يحمل nosuid/noexec؛ يبقى بعد إعادة التشغيل |
| 2 | /dev/shm | tmpfs، عادةً متساهل؛ يُمسح عند إعادة التشغيل |
| 3 | /tmp | غالبًا محصّن على أنظمة CIS/STIG |
| 4 | $HOME | الملاذ الأخير؛ دائمًا قابل للكتابة من قبل المستخدم |
إذا كانت جميع المرشحات محظورة يخرج البرنامج النصي برسالة خطأ واضحة بدلاً من الفشل بصمت.
| عائلة التوزيعات | أداة الحزم | تم الاختبار |
|---|---|---|
| Debian / Ubuntu | dpkg-deb | ✓ |
| RHEL / Fedora | rpmbuild | ✓ |
| SUSE / openSUSE | rpmbuild | ✓ |
تُدرج مؤشرات الاختراق من المستوى العام/البنية التحتية وصولًا إلى آثار البرنامج النصي المحددة. سيكتشف الكشف المبني على المؤشرات العامة هذه الثغرة بغض النظر عن متغير PoC المستخدم.