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-
Повышение привилегийАнализ уязвимостейЭксплуатацияТестирование на ПроникновениеСтатьи и ИсследованияОбучение и ОбразованиеЭксплуатация Бинарных Файлов
GitHub

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
sornphut/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.

Репозиторий
131 год назадЕщё не проверено

Qualys Security Advisory

Baron Samedit: Переполнение буфера в куче в Sudo (CVE-2021-3156)

======================================================================== Содержание

Краткое описание Анализ Эксплуатация Благодарности Временная шкала

======================================================================== Краткое описание

Мы обнаружили переполнение буфера в куче в Sudo (https://www.sudo.ws/). Эта уязвимость:

  • эксплуатируется любым локальным пользователем (обычные пользователи и системные пользователи, sudoers и не-sudoers), без аутентификации (т.е. атакующему не нужно знать пароль пользователя);

  • была внесена в июле 2011 года (коммит 8255ed69) и затрагивает все устаревшие версии с 1.8.2 по 1.8.31p2 и все стабильные версии с 1.9.0 по 1.9.5p1, в их конфигурации по умолчанию.

Мы разработали три различных эксплойта для этой уязвимости и получили полные привилегии root на Ubuntu 20.04 (Sudo 1.8.31), Debian 10 (Sudo 1.8.27) и Fedora 33 (Sudo 1.9.2). Другие операционные системы и дистрибутивы, вероятно, также уязвимы.

======================================================================== Анализ

Если Sudo выполняется для запуска команды в «командном» режиме (shell -c command):

  • либо через опцию -s, которая устанавливает флаг MODE_SHELL в Sudo;

  • либо через опцию -i, которая устанавливает флаги MODE_SHELL и MODE_LOGIN_SHELL;

то в начале функции 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 }

Скачать инструмент