Sploitus

Exploit for CVE-2021-3156

kitploit · 2026-08-27

Exploit Code

MARKDOWN80 lines
## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-LMOL-CVE-2021-3156
# Название проекта

Генератор эксплойта для CVE-2021-3156 sudo

## Установка

  1. Установите зависимости: ./install.sh
  2. Запустите генератор эксплойта: ./run.sh
  3. Если версия sudo в системе уязвима, генерируется эксплойт для установленной версии
  4. Эксплойт генерируется в exploit.c, а бинарный файл — ./exploit



## Требования

  1. gdb gcc make python3 python3-distro
  2. glibc с tcache
  3. В настоящее время поддерживаются ОС Ubuntu, Debian.



## Протестировано

  * Ubuntu 20.04.1
  * Ubuntu 20.04.2
  * Ubuntu 20.10
  * Ubuntu 18.04.5
  * Debian 10.7.0



## Автор

  * **Luis Molina Garzón** \- (https://gitlab.iesvirgendelcarmen.com/luis/CVE-2021-3156/)

  * **Qualys Research Team.** (https://blog.qualys.com/vulnerabilities-research/2021/01/26/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit)




## Уязвимость

  * sudo экранирует метасимволы в функции parse_args в main
  * Затем в set_cmnd удаляются escape-символы, за которыми не следует пробел
  * sudo предполагает, что parse_args является предусловием для set_cmnd.
  * Проблема в том, что условия различаются в каждом парсере. Первый выполняется, если режим (MODE_RUN && MODE_SHELL). Второй выполняется, если режим (MODE_RUN | MODE_EDIT | MODE_CHECK) И (MODE_SHELL|MODE_LOGIN_SHELL)
  * Существует способ не выполнять первый парсер, но выполнить второй: sudoedit -s
  * set_cmnd вычисляет размер аргументов и создаёт chunk в куче для их объединения. Затем он копирует каждый аргумент до нулевого байта и переходит к следующему. Если входной аргумент заканчивается символом '\', set_cmnd пропускает escape-символ, копирует нулевой байт, но продолжает копировать следующий аргумент как часть того же самого. Это приводит к переполнению буфера в куче.
  * Таким образом, если последний аргумент заканчивается на '\', set_cmnd переполняет буфер содержимым первой переменной окружения. Если эта переменная окружения заканчивается на '\', он продолжит копировать следующую.



## Генератор эксплойта

  * Используется метод 2, описанный в (https://packetstormsecurity.com/files/161160/Sudo-Heap-Based-Buffer-Overflow.html)
  * sudo использует glibc nsswitch для чтения базы данных group после переполнения.
  * nsswitch создаёт структуру данных service_table в куче со всеми базами данных и службами из nsswitch.conf.
  * Службы group имеют тип struct service_user.
  * Структура имеет поле name с именем службы.
  * nsswitch динамически загружает библиотеку libnss_[имя_службы]_.so.2 в зависимости от конфигурации /etc/nsswitch.conf для каждой службы базы данных group.
  * Указатель library должен быть перезаписан на NULL, чтобы избежать краха. Кроме того, это заставляет перезагрузить библиотеку в память, на этот раз локальную библиотеку с шеллкодом.
  * Используется техника heap grooming или feng shui. Создаются «локальные» переменные окружения переменного размера для формирования раскладки кучи, позволяющей приблизить chunk, в который set_cmnd копирует аргументы, к цели — структуре service_user для group.
  * Непосредственно перед вызовом malloc в set_cmnd просматривается tcache кучи, чтобы увидеть первые chunk'и, которые будут переработаны, и их размеры.
  * Сортируются chunk'и, образующие базы данных и службы nsswitch. Они обходятся упорядоченно. Сохраняется адрес памяти целевого chunk'а и предыдущего.
  * В bin tcache ищется chunk в этом диапазоне.
  * Как только позиция chunk'а и его размер известны, генерируется эксплойт.
  * Используется аргумент, заканчивающийся на '\' и нулевой байт точного размера, чтобы этот chunk был переработан.
  * Создаются точные «локальные» переменные окружения для создания правильной раскладки.
  * Перед этими «локальными» переменными генерируется переменная окружения необходимого размера, чтобы достичь целевой структуры.
  * Целевая структура перезаписывается нулевыми байтами с помощью массивов строк с escape-символом '\', что приводит к записи нулевого байта в set_cmnd.
  * Поле name структуры service_user перезаписывается на 'x/x', чтобы впоследствии загрузилась библиотека 'libnss_x/x.so.2'
  * В библиотеке создаётся конструктор, который выполняет шеллкод.
  * Поскольку sudo выполняется с suid-битом, полученная оболочка принадлежит root.



## Лицензия

Этот проект распространяется под лицензией GNU GPL