Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2021-3560 — تحليل متعمق لـ CVE-2021-3560، وهي ثغرة تصعيد امتيازات محلية في Linux PolKit. يتضمن تحليل السبب الجذري، وآليات الاستغلال، وعرضًا توضيحيًا لحالة السباق (race condition) التي تؤدي إلى الوصول بصلاحيات الجذر (root access). | Kitploit
أدوات/GitHubGitHub/chenaotian/cve-2021-3560
تصعيد الامتيازاتتحليل الثغرات الأمنيةالاستغلالتحليل الملفات الثنائيةالتعلم والتعليم
GitHubchenaotian/cve-2021-3560

CVE-2021-3560

تحليل متعمق لـ CVE-2021-3560، وهي ثغرة تصعيد امتيازات محلية في Linux PolKit. يتضمن تحليل السبب الجذري، وآليات الاستغلال، وعرضًا توضيحيًا لحالة السباق (race condition) التي تؤدي إلى الوصول بصلاحيات الجذر (root access).

عرض المستودع
936منذ 4 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2021-3560 تحليل تصعيد الامتيازات المحلية من خلال سباق الشروط في PolKit

[toc]

ملخص الثغرة

رقم الثغرة: CVE-2021-3560

تقييم الثغرة:

المنتج المتأثر: linux PolKit (polkitd)

نطاق التأثير: تم إدخاله في الكود المصدري 0.113؛ https://www.venustech.com.cn/new_type/aqtg/20210611/22788.html

  • RHEL 8
  • Fedora 21 والإصدارات الأحدث
  • Debian testing ("bullseye")
  • Ubuntu 20.04

شروط الاستغلال: محلي على لينكس؛ وجود dbus + polkitd

تأثير الاستغلال: تصعيد امتيازات محلي

الحصول على الكود المصدري:

  • polkit-0.113: https://launchpad.net/debian/+source/policykit-1/0.113-5
  • accountsservice: apt source accountsservice
  • dbus: apt source dbus

إعداد البيئة

يمكن إعادة إنتاج الثغرة باستخدام الصورة الافتراضية لـ ubuntu-20.04.2: http://old-releases.ubuntu.com/releases/20.04.2/ubuntu-20.04.2-desktop-amd64.iso

مبدأ الثغرة

موقع حدوث الثغرة

أولاً، ننظر إلى الكود الذي توجد به المشكلة

/polkit-0.113/src/polkit/polkitsystembusname.c : 388 : polkit_system_bus_name_get_creds_sync

static void
on_retrieved_unix_uid_pid (GObject              *src,
			   GAsyncResult         *res,
			   gpointer              user_data)
{
  AsyncGetBusNameCredsData *data = user_data;
  GVariant *v;

  v = g_dbus_connection_call_finish ((GDBusConnection*)src, res,
				     data->caught_error ? NULL : data->error);
  if (!v)
    {
      data->caught_error = TRUE; // تعيين بت الخطأ بعد الفشل لسبب ما
    }
  else
  {
      ··· ···// معالجة البيانات عند النجاح
  }
  ··· ···
}

static gboolean
polkit_system_bus_name_get_creds_sync (PolkitSystemBusName           *system_bus_name,
				       guint32                       *out_uid,
				       guint32                       *out_pid,
				       GCancellable                  *cancellable,
				       GError                       **error)
{
  gboolean ret = FALSE;
  AsyncGetBusNameCredsData data = { 0, }; // تم تهيئة data إلى 0
  ··· ···
  g_dbus_connection_call (connection,
			  "org.freedesktop.DBus",       /* name */
			  "/org/freedesktop/DBus",      /* object path */
			  "org.freedesktop.DBus",       /* interface name */
			  "GetConnectionUnixUser",      /* method */
			  g_variant_new ("(s)", system_bus_name->name),
			  G_VARIANT_TYPE ("(u)"),
			  G_DBUS_CALL_FLAGS_NONE,
			  -1,
			  cancellable,
			  on_retrieved_unix_uid_pid, // دالة الاسترجاع
			  &data);
  g_dbus_connection_call (connection,
			  "org.freedesktop.DBus",       /* name */
			  "/org/freedesktop/DBus",      /* object path */
			  "org.freedesktop.DBus",       /* interface name */
			  "GetConnectionUnixProcessID", /* method */
			  g_variant_new ("(s)", system_bus_name->name),
			  G_VARIANT_TYPE ("(u)"),
			  G_DBUS_CALL_FLAGS_NONE,
			  -1,
			  cancellable,
			  on_retrieved_unix_uid_pid, // دالة الاسترجاع
			  &data);

  while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error))
    g_main_context_iteration (tmp_context, TRUE); // انتظار اكتمال تنفيذ الناقل، ومعالجة uid و pid كلاهما أو حدوث استثناء

  if (out_uid)
    *out_uid = data.uid;
  if (out_pid)
    *out_pid = data.pid;
  ret = TRUE; // TRUE في جميع الأحوال؟
 out:
  if (tmp_context)
    {
      g_main_context_pop_thread_default (tmp_context);
      g_main_context_unref (tmp_context);
    }
  if (connection != NULL)
    g_object_unref (connection);
  return ret;
}

في دالة polkit_system_bus_name_get_creds_sync، تقوم هذه الدالة بالمصادقة على بعض الطلبات (سيتم شرح المنطق المحدد لاحقًا). يتم استدعاء طريقتي GetConnectionUnixUser و GetConnectionUnixProcessID تباعًا عبر ناقل org.freedesktop.DBus. هاتان الطريقتان مقدمة من ناقل org.freedesktop.DBus، وتقومان بالحصول على PID العملية الطالبة ومعرف المستخدم (UID)، ثم يتم تمريرهما إلى دالة الاسترجاع on_retrieved_unix_uid_pid لمعالجة البيانات المرتجعة. بعد ذلك، يتم حظر التنفيذ حتى تنتهي العملية على جانب الناقل.

يمكن ملاحظة من دالة on_retrieved_unix_uid_pid أنه يتم تعيين ما إذا كان هناك استثناء (error?) بناءً على نتيجة التنفيذ من جانب الناقل، ثم يتم تعيين بت الاستثناء. إذا تم التنفيذ بنجاح، يتم إرجاع معرف المستخدم أو PID العملية بشكل طبيعي. ولكن في دالة polkit_system_bus_name_get_creds_sync، بعد الحظر وانتظار نتيجة الناقل (العلامة على اكتمال المعالجة هي أن كلاً من UID و PID تمت معالجتهما أو حدوث استثناء). بمعنى آخر، من الناحية المنطقية، هناك ثلاث نتائج محتملة لعودة الناقل: الحصول على UID 0 (مستخدم مميز)؛ الحصول على UID غير 0 (مستخدم عادي)؛ استثناء. ولكن في المعالجة اللاحقة، لا يتم معالجة الاستثناء، بل يتم تعيين out_uid الذي سيتم إرجاعه إلى الطبقة العليا مباشرةً إلى data.uid الذي عاد من الناقل، ثم يتم تعيين ret إلى TRUE مباشرةً:

  while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error))
    g_main_context_iteration (tmp_context, TRUE); // انتظار اكتمال تنفيذ الناقل، ومعالجة uid و pid كلاهما أو حدوث استثناء

  if (out_uid)
    *out_uid = data.uid;
  if (out_pid)
    *out_pid = data.pid;
  ret = TRUE; // TRUE في جميع الأحوال؟

لكن تم تجاهل حالة واحدة وهي أن تنفيذ ناقل DBUS قد يؤدي إلى استثناء، مما يتسبب في قيام دالة الاسترجاع بتعيين بت الاستثناء والعودة دون معالجة بيانات data، بينما data مهيأة بـ 0، مما يؤدي إلى تعيين out_uid لاحقًا إلى 0، وهو المستخدم المميز.

فأين تُستخدم دالة polkit_system_bus_name_get_creds_sync التي بها مشكلة؟

مسار التشغيل

العملية التي يوجد بها الخلل هي عملية polkitd:

polkit عبارة عن مجموعة أدوات على مستوى التطبيق، والتي تحقق الاتصال بين العمليات ذات الأولويات المختلفة من خلال تعريف ومراجعة قواعد الإذن: يتركز قرار التحكم في إطار موحد، ليحدد ما إذا كانت العملية منخفضة الأولوية لها الحق في الوصول إلى عملية عالية الأولوية.

باختصار، هذه عملية جذرية تعمل في الخلفية، وتقوم بتقييم الإذن للعمليات الأخرى منخفضة الصلاحية عند الوصول إلى الوظائف التي توفرها العمليات عالية الصلاحية من خلال الاتصال بين العمليات. نظرًا لأن هذه العملية ستعيد التشغيل إذا تم إرفاق gdb بها، يمكننا فقط تحليلها على مستوى الكود المصدري لإيجاد مسار تشغيل الدالة المخترقة:

يستخدم polkitd بشكل كبير إطار عمل gio DBUS للاتصال بين العمليات، يمكنك الاطلاع على الدليل مسبقًا، والتركيز على بعض الدوال المهمة وما إلى ذلك.

الآن نقوم بتحليل مسار تشغيل الثغرة في polkitd:

  1. أولاً هي main:

    polkit-0.113\src\polkitbackend\polkitd.c : 155 : main

    int
    main (int    argc,
          char **argv)
    {
      ··· ···
      ··· ···
    
      loop = g_main_loop_new (NULL, FALSE);
    
      sigint_id = g_unix_signal_add (SIGINT,
                                     on_sigint,
                                     NULL);
    
      name_owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
                                      "org.freedesktop.PolicyKit1",  // تسجيل اسم ناقل
                                      G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
                                        (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
                                      on_bus_acquired, // دالة الاسترجاع عند الوصول إلى هذا الناقل
                                      on_name_acquired,
                                      on_name_lost,
                                      NULL,
                                      NULL);
    
      g_print ("Entering main event loop\n");
      g_main_loop_run (loop); // بدء الحلقة
      ··· ···
      ··· ···
    }
    
  2. أولاً يتم تسجيل ناقل باسم org.freedesktop.PolicyKit1، ثم هناك ثلاث دوال استرجاع، نركز على on_bus_acquired، والتي سيتم استدعاؤها عند الوصول إلى الناقل.

  3. في دالة on_bus_acquired، يتم استدعاء دالة تسجيل نوع تسمى polkit_backend_authority_register مباشرةً.

  4. في دالة polkit_backend_authority_register، يتم تسجيل كائن واجهة باسم org.freedesktop.PolicyKit1.Authority، ويتم تمرير جدول دوال استرجاع باسم server_vtable. نقطة تشغيل الثغرة موجودة في إحدى دوال هذا الجدول:

    policykit-1_0.113.orig\polkit-0.113\src\polkitbackend\polkitbackendauthority.c : 1333 : server_vtable

تنزيل الأداة