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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2021-4034 — كتابة مفصلة واستغلال إثبات مفهوم لـ CVE-2021-4034 (تصعيد امتيازات محلية في PolKit pkexec)، بما في ذلك بيئة معمل Docker للتحليل والتصحيح العملي. | Kitploit
أدوات/GitHubGitHub/chenaotian/cve-2021-4034
تصعيد الامتيازاتتحليل الثغرات الأمنيةالاستغلالاختبار الاختراقالتعلم والتعليماستغلال الملفات الثنائيةمختبرات وتدريب عملي
GitHubchenaotian/cve-2021-4034

CVE-2021-4034

كتابة مفصلة واستغلال إثبات مفهوم لـ CVE-2021-4034 (تصعيد امتيازات محلية في PolKit pkexec)، بما في ذلك بيئة معمل Docker للتحليل والتصحيح العملي.

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

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2021-4034 تحليل رفع الامتيازات المحلية لـ PolKit

[toc]

نظرة عامة على الثغرة

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

تصنيف الثغرة:

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

النطاق المتأثر: الإصدارات من 2009 حتى الآن (الحالي 0.105) راجع http://its.dlut.edu.cn/info/1054/78309.htm

شروط الاستغلال: محلي على لينكس؛ ملف pkexec هو suid ولديه صلاحية التنفيذ

الحصول على المصدر: apt source policykit-1 أو https://launchpad.net/ubuntu/bionic/+package/policykit-1

بيئة Docker

بيئة Docker: chenaotian/cve-2021-4034

Docker الذي أنشأته يوفر:

  1. pkexec مترجم ذاتيًا مع إمكانية تصحيح الأخطاء من المصدر
  2. glibc مع رموز التصحيح (يبدو غير مفيد)
  3. gdb وإضافات gdb pwngdb & pwndbg (يبدو غير ضروري)
  4. الـ exp في بيئة التصحيح

كل شيء موجود في الدليل /root/:

image-20220126183638493

  • دليل exp هو الدليل الذي يحتوي على exp و run.sh، يمكنك التبديل إلى المستخدم test باستخدام su test ثم التشغيل
  • glibc-2.27 هو دليل شفرة glibc المصدرية، على الأرجح لن تحتاجه، لكنه مفيد لتصحيح الأخطاء المصدرية باستخدام gdb عند الحاجة
  • polkit-0.105 هو حزمة شفرة policykit المصدرية

تشغيل Docker:

docker run -d -ti --rm -h cvedebug --name cvedebug --cap-add=SYS_PTRACE chenaotian/cve-2021-4034:latest /bin/bash

اختبار الـ exp:

cd ~/exp/CVE-2021-4034/
./run.sh
su test
./exp
whoami

مبدأ الثغرة

المنتج الذي تحدث فيه الثغرة هو أمر pkexec ضمن polkit. يشبه pkexec أداة sudo حيث يسمح لنا بتنفيذ الأوامر كمستخدم آخر (عادةً root). يمكن معرفة الحزمة التي ينتمي إليها pkexec باستخدام الأمر dpkg:

dpkg -S /usr/bin/pkexec

image-20220126152839307

ثم الحصول على حزمة المصدر (موجودة أيضًا في Docker الخاص بي)، وبعد ذلك تجميع إصدار قابل للتصحيح من حزمة المصدر لتسهيل التصحيح.

نقطة إطلاق الثغرة

مبدأ إطلاق الثغرة بسيط للغاية

/polkit-0.105/src/programs/pkexec.c : 386 main

int
main (int argc, char *argv[])
{
    
  ··· ···
  ··· ···
      
  /* هذا يعني تكرار المعاملات المدخلة من المستخدم وتعيين القيم بناءً على معاملات مختلفة
   * لكن المشكلة أن نقطة البداية للتكرار هي 1، دون مراعاة حالة عدم إدخال المستخدم لأي معاملات
   */
  for (n = 1; n < (guint) argc; n++) 
    {
      if (strcmp (argv[n], "--help") == 0)
        {
          opt_show_help = TRUE;
        }
      ··· ···
      else // إذا كان المعامل غير معروف، يتم الخروج من الحلقة، مما يعني أن هذا المعامل هو الأمر المطلوب تنفيذه
        {
          break;
        }
    }

  ··· ···

  g_assert (argv[argc] == NULL);
  path = g_strdup (argv[n]); // الحصول على السلسلة النصية للأمر المراد تنفيذه
  if (path == NULL)
    {
      ···
    }
  if (path[0] != '/')
    {
      /* g_find_program_in_path() is not suspectible to attacks via the environment */
      // هذه الدالة تبحث عن المسار المطلق للأمر وفقًا لمتغير البيئة PATH
      s = g_find_program_in_path (path); 
      if (s == NULL)
        {
          ···
        }
      g_free (path);
      argv[n] = path = s;// تعديل معامل سطر الأوامر بالمسار المطلق الذي تم الحصول عليه
    }
  ··· ···
  ··· ···

تحليل استنادًا إلى تعليقاتي في الكود:

  1. أولاً، في الدالة main، يتم تعيين بعض المتغيرات بناءً على معاملات سطر الأوامر، لكن قيمة بداية حلقة for هي 1، مما يعني أنها تفترض افتراضيًا أننا سنقدم معاملًا واحدًا على الأقل (الأمر المراد تنفيذه بواسطة pkexec)
  2. إذا تم العثور على معامل سطر أوامر لا يبدأ بـ --، يُعتبر هذا الأمر هو المراد تنفيذه، ويتم الخروج من الحلقة لتنفيذ المنطق التالي.
  3. يتم استدعاء الدالة g_find_program_in_path للبحث عن المسار المطلق للأمر. تبحث الدالة وفقًا لمتغير البيئة PATH عن المسار المطلق للمعامل المُمرر (الأمر). على سبيل المثال، إدخال cat يُرجع /bin/cat.
  4. يتم كتابة المسار المطلق المُعاد في موقع معامل سطر الأوامر (يمكن فهمه على أنه تحويل الأمر إلى المسار المطلق للملف المقابل للأمر).

من السهل فهمه، لكن المشكلة تكمن في:

  1. عند تشغيل برنامج ثنائي في لينكس، يتم وضع معاملات سطر الأوامر argv[] ومتغيرات البيئة environ[] في أسفل المكدس، وهما متصلان. العنصر الأخير في argv[] هو null.

    image-20220126162140802

  2. إذا تم تشغيل pkexec من سطر الأوامر دون أي معاملات أخرى، فإن argv[0] سيكون "pkexec" و argv[1] سيكون \x00، لا مشكلة. لكن إذا تم تشغيل pkexec باستخدام الدالة execve دون أي معاملات أخرى، فإن argv[0] سيكون \x00 و argv[1] سيكون متغير بيئة! عند قراءة argv[1]، سيتم قراءة environ[0] خارج الحدود (out-of-bounds).

    تشغيل pkexec مباشرة من سطر الأوامر، argc = 1، argv[0] هو مسار pkexec:

    image-20220126162616203

    تشغيل pkexec باستخدام execve، argc = 0:

    image-20220126162804529

إذن ما هو التأثير؟ عند التشغيل باستخدام execve دون أي معاملات أخرى، فإن طول argv[] يساوي 0، وبالتالي argv[1] هو environ[0]. وبهذا يصبح المنطق الذي تم تحليله أعلاه هو: الحصول على قيمة أول متغير بيئة، والبحث عن مساره المطلق في متغير البيئة PATH. إذا تم العثور عليه، يتم كتابته مرة أخرى في أول متغير بيئة. وبالتالي تكون طريقة الاستغلال كالتالي:

استغلال الثغرة

أول شيء يجب توضيحه هو أن pkexec هو ملف امتياز (suid):

image-20220126161324831

كيف يمكن استغلال متغيرات البيئة في ملف امتياز؟ أولاً، دعنا نفهم تفصيلًا صغيرًا:

تفصيل صغير

يقوم المُحمل الديناميكي في لينكس ld-linux-x86-64.so.2 بمسح متغيرات البيئة الحساسة عند تنفيذ برامج الامتياز:

الدالة _dl_non_dynamic_init: glibc-2.27/elf/dl-support.c : 307

void
_dl_non_dynamic_init (void)
{
  ··· ···
  ··· ···

  if (__libc_enable_secure) // في حالة وضع الامتياز
    {
      static const char unsecure_envvars[] =
	UNSECURE_ENVVARS
#ifdef EXTRA_UNSECURE_ENVVARS
	EXTRA_UNSECURE_ENVVARS
#endif
	;
      const char *cp = unsecure_envvars;

      // تكرار لمسح جميع متغيرات البيئة في قائمة المتغيرات الخطرة (unset)
      while (cp < unsecure_envvars + sizeof (unsecure_envvars)) 
	{
	  __unsetenv (cp);
	  cp = (const char *) __rawmemchr (cp, '\0') + 1;
	}

#if !HAVE_TUNABLES
      if (__access ("/etc/suid-debug", F_OK) != 0)
	__unsetenv ("MALLOC_CHECK_");
#endif
    }
··· ···
··· ···
}

قائمة متغيرات البيئة الخطرة UNSECURE_ENVVARS معرفة كالتالي:

glibc-2.27/sysdeps/generic/unsecvars.h : 10

#define GLIBC_TUNABLES_ENVVAR "GLIBC_TUNABLES\0"
#define UNSECURE_ENVVARS \
  "GCONV_PATH\0"							      \
  "GETCONF_DIR\0"							      \
  GLIBC_TUNABLES_ENVVAR							      \
  "HOSTALIASES\0"							      \
  "LD_AUDIT\0"								      \
  "LD_DEBUG\0"								      \
  "LD_DEBUG_OUTPUT\0"							      \
  "LD_DYNAMIC_WEAK\0"							      \
  "LD_HWCAP_MASK\0"							      \
  "LD_LIBRARY_PATH\0"							      \
  "LD_ORIGIN_PATH\0"							      \
  "LD_PRELOAD\0"							      \
  "LD_PROFILE\0"							      \
  "LD_SHOW_AUXV\0"							      \
  "LD_USE_LOAD_BIAS\0"							      \
  "LOCALDOMAIN\0"							      \
  "LOCPATH\0"								      \
  "MALLOC_TRACE\0"							      \
  "NIS_PATH\0"								      \
  "NLSPATH\0"								      \
  "RESOLV_HOST_CONF\0"							      \
  "RES_OPTIONS\0"							      \
  "TMPDIR\0"								      \
  "TZDIR\0"

عند اكتشاف أن البرنامج هو ملف امتياز (suid)، يتم مسح متغيرات البيئة هذه. يمكن ملاحظة أن معظمها من سلسلة LD_، والتي لديها القدرة على تحديد مسار تحميل المكتبات الديناميكية. هذا لمنع المستخدمين ذوي الصلاحيات المنخفضة من جعل برامج suid تحمل ملفات so غير موثوقة عبر هذه المتغيرات، مما قد يؤدي إلى تنفيذ كود ضار ورفع الامتيازات.

تنزيل الأداة