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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2021-3156-Heap-Based-Buffer-Overflow-in-Sudo-Baron-Samedit- — تحليل فني وتطوير استغلال لـ CVE-2021-3156، وهو تجاوز سعة مخزن مؤقت في الكومة في Sudo، بما في ذلك ثلاثة استغلالات عاملة لتصعيد الامتيازات المحلي على توزيعات Linux الرئيسية. | Kitploit
أدوات/GitHubGitHub/sornphut/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit-
تصعيد الامتيازاتتحليل الثغرات الأمنيةالاستغلالاختبار الاختراقالأوراق والأبحاثالتعلم والتعليماستغلال الملفات الثنائية
GitHubsornphut/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit-

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2021-3156-Heap-Based-Buffer-Overflow-in-Sudo-Baron-Samedit-

تحليل فني وتطوير استغلال لـ CVE-2021-3156، وهو تجاوز سعة مخزن مؤقت في الكومة في Sudo، بما في ذلك ثلاثة استغلالات عاملة لتصعيد الامتيازات المحلي على توزيعات Linux الرئيسية.

عرض المستودع
14منذ سنة واحدةلم تتم المراجعة بعد

Qualys Security Advisory

Baron Samedit: تجاوز سعة المخزن المؤقت في الكومة في Sudo (CVE-2021-3156)

======================================================================== المحتويات

الملخص التحليل الاستغلال الشكر الجدول الزمني

======================================================================== الملخص

اكتشفنا تجاوزًا لسعة المخزن المؤقت في الكومة في Sudo (https://www.sudo.ws/). هذه الثغرة:

  • قابلة للاستغلال من قبل أي مستخدم محلي (المستخدمون العاديون ومستخدمو النظام، sudoers وغير sudoers)، بدون مصادقة (أي أن المهاجم لا يحتاج لمعرفة كلمة مرور المستخدم)؛

  • تم إدخالها في يوليو 2011 (commit 8255ed69)، وتؤثر على جميع الإصدارات القديمة من 1.8.2 إلى 1.8.31p2 وجميع الإصدارات المستقرة من 1.9.0 إلى 1.9.5p1، في تكوينها الافتراضي.

قمنا بتطوير ثلاثة استغلالات مختلفة لهذه الثغرة، وحصلنا على صلاحيات الجذر الكاملة على Ubuntu 20.04 (Sudo 1.8.31)، وDebian 10 (Sudo 1.8.27)، وFedora 33 (Sudo 1.9.2). من المحتمل أن تكون أنظمة التشغيل والتوزيعات الأخرى قابلة للاستغلال أيضًا.

======================================================================== التحليل

إذا تم تنفيذ Sudo لتشغيل أمر في وضع "shell" (shell -c command):

  • إما عبر الخيار -s، الذي يضع علامة MODE_SHELL الخاصة بـ Sudo؛

  • أو عبر الخيار -i، الذي يضع علامتي MODE_SHELL و MODE_LOGIN_SHELL الخاصتين بـ Sudo؛

عندها، في بداية main() الخاصة بـ Sudo، تقوم parse_args() بإعادة كتابة argv (الأسطر 609-617)، عن طريق دمج جميع وسائط سطر الأوامر (الأسطر 587-595) وهروب جميع الأحرف الوصفية باستخدام الخطوط المائلة العكسية (الأسطر 590-591):


571 if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) { 572 char **av, *cmnd = NULL; 573 int ac = 1; ... 581 cmnd = dst = reallocarray(NULL, cmnd_size, 2); ... 587 for (av = argv; *av != NULL; av++) { 588 for (src = *av; src != '\0'; src++) { 589 / quote potential meta characters */ 590 if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '$') 591 *dst++ = '\'; 592 *dst++ = *src; 593 } 594 dst++ = ' '; 595 } ... 600 ac += 2; / -c cmnd */ ... 603 av = reallocarray(NULL, ac + 1, sizeof(char *)); ... 609 av[0] = (char )user_details.shell; / plugin may override shell */ 610 if (cmnd != NULL) { 611 av[1] = "-c"; 612 av[2] = cmnd; 613 } 614 av[ac] = NULL; 615 616 argv = av; 617 argc = ac; 618 }

لاحقًا، في sudoers_policy_main()، تقوم set_cmnd() بدمج وسائط سطر الأوامر في مخزن مؤقت قائم على الكومة "user_args" (الأسطر 864-871) وتفكيك الأحرف الوصفية (الأسطر 866-867)، "لأغراض مطابقة sudoers وتسجيل الدخول":


819 if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { ... 852 for (size = 0, av = NewArgv + 1; *av; av++) 853 size += strlen(*av) + 1; 854 if (size == 0 || (user_args = malloc(size)) == NULL) { ... 857 } 858 if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) { ... 864 for (to = user_args, av = NewArgv + 1; (from = *av); av++) { 865 while (*from) { 866 if (from[0] == '\' && !isspace((unsigned char)from[1])) 867 from++; 868 *to++ = *from++; 869 } 870 *to++ = ' '; 871 } ... 884 } ... 886 }

لسوء الحظ، إذا انتهت وسيطة سطر أوامر بحرف خط مائل عكسي واحد، فعندها:

  • في السطر 866، "from[0]" هو حرف الخط المائل العكسي، و"from[1]" هو المنهي الصفري للوسيطة (أي ليس حرف مسافة)؛

  • في السطر 867، يتم زيادة "from" ويشير إلى المنهي الصفري؛

  • في السطر 868، يتم نسخ المنهي الصفري إلى المخزن المؤقت "user_args"، ويتم زيادة "from" مرة أخرى ويشير إلى الحرف الأول بعد المنهي الصفري (أي خارج حدود الوسيطة)؛

  • حلقة "while" في الأسطر 865-869 تقرأ وتنسخ أحرفًا خارج الحدود إلى المخزن المؤقت "user_args".

بمعنى آخر، set_cmnd() معرضة لتجاوز سعة المخزن المؤقت في الكومة، لأن الأحرف خارج الحدود التي يتم نسخها إلى المخزن المؤقت "user_args" لم تكن مدرجة في حجمه (المحسوب في الأسطر 852-853).

من الناحية النظرية، ومع ذلك، لا يمكن لأي وسيطة سطر أوامر أن تنتهي بحرف خط مائل عكسي واحد: إذا تم تعيين MODE_SHELL أو MODE_LOGIN_SHELL (السطر 858، شرط ضروري للوصول إلى الكود الضعيف)، فإن MODE_SHELL يتم تعيينها (السطر 571) وقد قامت parse_args() بالفعل بهروب جميع الأحرف الوصفية، بما في ذلك الخطوط المائلة العكسية (أي أنها هربت كل خط مائل عكسي بخط مائل عكسي ثانٍ).

من الناحية العملية، ومع ذلك، فإن الكود الضعيف في set_cmnd() وكود الهروب في parse_args() محاطان بشروط مختلفة قليلاً:


819 if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { ... 858 if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {

مقابل:


571 if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) {

سؤالنا، إذن، هو: هل يمكننا تعيين MODE_SHELL وإما MODE_EDIT أو MODE_CHECK (للوصول إلى الكود الضعيف) ولكن ليس MODE_RUN الافتراضي (لتجنب كود الهروب)؟

الجواب، على ما يبدو، هو لا: إذا قمنا بتعيين MODE_EDIT (خيار -e، السطر 361) أو MODE_CHECK (خيار -l، السطران 423 و519)، فإن parse_args() تزيل MODE_SHELL من "valid_flags" (السطران 363 و424) وتخرج مع وجود خطأ إذا حددنا علامة غير صالحة مثل MODE_SHELL (الأسطر 532-533):


358 case 'e': ... 361 mode = MODE_EDIT; 362 sudo_settings[ARG_SUDOEDIT].value = "true"; 363 valid_flags = MODE_NONINTERACTIVE; 364 break; ... 416 case 'l': ... 423 mode = MODE_LIST; 424 valid_flags = MODE_NONINTERACTIVE|MODE_LONG_LIST; 425 break; ... 518 if (argc > 0 && mode == MODE_LIST) 519 mode = MODE_CHECK; ... 532 if ((flags & valid_flags) != flags) 533 usage(1);

لكننا وجدنا ثغرة: إذا قمنا بتنفيذ Sudo كـ "sudoedit" بدلاً من "sudo"، فإن parse_args() تقوم تلقائيًا بتعيين MODE_EDIT (السطر 270) ولكنها لا تعيد تعيين "valid_flags"، وتتضمن "valid_flags" MODE_SHELL افتراضيًا (السطران 127 و249):


127 #define DEFAULT_VALID_FLAGS (MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME|MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_SHELL) ... 249 int valid_flags = DEFAULT_VALID_FLAGS; ... 267 proglen = strlen(progname); 268 if (proglen > 4 && strcmp(progname + proglen - 4, "edit") == 0) { 269 progname = "sudoedit"; 270 mode = MODE_EDIT; 271 sudo_settings[ARG_SUDOEDIT].value = "true"; 272 }

وبالتالي، إذا قمنا بتنفيذ "sudoedit -s"، فإننا نضبط كلاً من MODE_EDIT و MODE_SHELL (ولكن ليس MODE_RUN)، ونتجنب كود الهروب، ونصل إلى الكود الضعيف، ونحدث تجاوزًا لسعة المخزن المؤقت في الكومة "user_args" من خلال وسيطة سطر أوامر تنتهي بحرف خط مائل عكسي واحد:

تنزيل الأداة