
CVE-2021-3156 (Baron Samedit) Report and Research
Автор: IJ Baig
Дата: 7 июля 2026 года
1.8.2 по 1.8.31p2, а также стабильные версии с 1.9.0 по 1.9.5p1.1.9.5p1Для безопасного анализа этой уязвимости уязвимая версия Sudo была скомпилирована в изолированной, непродакшн-среде.

Исходный код Sudo 1.9.5p1 был загружен и скомпилирован локально с использованием стандартных утилит make. Особое внимание было уделено тому, чтобы сборка выполнялась из локального каталога и не перезаписывала нативный пропатченный бинарный файл sudo хост-системы.

Подтверждение сборки: После компиляции был запущен пользовательский бинарный файл, чтобы убедиться, что была собрана именно уязвимая версия.


plugins/sudoers/sudoers.cset_cmnd() (примерно строка 864 в версии 1.9.5p1)
Представьте, что у вас есть помощник, чья задача — удалять escape-символы (обратные слеши) из списка слов перед тем, как поместить их в заново выделенное хранилище (буфер в куче). Помощник слепо предполагает, что за каждым обратным слешем всегда следует допустимый символ, поэтому при обнаружении обратного слеша он пропускает его и копирует следующий символ.
Однако в том, как программа обрабатывает аргументы при запуске sudoedit -s, существует изъян. Он позволяет пользователю незаметно добавить слово, которое заканчивается ровно одним обратным слешем (\), за которым сразу следует невидимый маркер конца слова (нулевой терминатор, \0).
Когда код помощника доходит до этого завершающего обратного слеша, он пропускает его и смотрит на следующий символ — нулевой терминатор. Вместо остановки логика оператора if заставляет помощника пропустить и нулевой терминатор. Цикл продолжается, копируя в хранилище любые произвольные данные из памяти за пределами допустимой области. Такое непрерывное копирование за пределы предполагаемой длины слова переполняет выделенный буфер, что приводит к серьёзному переполнению буфера в куче.
Фрагмент уязвимого кода:
/* Unescape characters, skipping over backslashes */
for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
while (*from) {
// VULNERABILITY: If from[0] is '\' and from[1] is '\0',
// the loop evaluates to true, increments 'from', skipping the null terminator.
if (from[0] == '\\' && !isspace((unsigned char)from[1]))
from++;
*to++ = *from++;
}
*to++ = ' ';
}
*--to = '\0';
Разработчики Sudo исправили эту логическую ошибку в версии 1.9.5p2, добавив строгую проверку границ. Теперь код явно проверяет, что символ, следующий за обратным слешем, не является нулевым терминатором, перед тем как выполнить его разэкранирование.
Дифф патча:
- if (from[0] == '\\' && !isspace((unsigned char)from[1]))
+ if (from[0] == '\\' && from[1] != '\0' && !isspace((unsigned char)from[1]))
Почему это устраняет первопричину:
Добавление проверки from[1] != '\0' немедленно останавливает чтение за пределами допустимой области. Теперь, если код встречает завершающий обратный слеш в самом конце строки (то есть from[1] — нулевой терминатор), оператор if принимает значение false. Указатель не инкрементируется преждевременно, нулевой терминатор корректно обрабатывается как конец строки, и цикл безопасно завершается без переполнения кучи.
Для этого воспроизведения использовался широко известный Python-эксплойт, разработанный исследователем безопасности Worawit (а именно вариант exploit_nss.py).
Перед выполнением PoC крайне важно понять его механику. Скрипт не просто вызывает сбой программы; он выполняет высокоточную манипуляцию памятью для получения выполнения кода.
Вот пошаговый разбор операций PoC:
.so). Эта нагрузка предназначена для выполнения /bin/sh с правами root.LC_ALL, LANG и TZ). Поскольку Sudo загружает переменные окружения в кучу при запуске, скрипт вычисляет точные размеры, необходимые для выстраивания кучи в предсказуемом порядке.sudoedit -s и передаёт аргумент командной строки, заканчивающийся одним обратным слешем. Это запускает уязвимость off-by-one, описанную в разделе 2, вызывая запись за пределами допустимой области.service_user. Эта структура используется Name Service Switch (NSS) для поиска системной информации.service_user повреждается таким образом, чтобы указывать на вредоносную библиотеку .so, скомпилированную на шаге 1. Когда Sudo пытается выполнить поиск привилегий пользователя, он вслепую загружает и выполняет библиотеку злоумышленника, предоставляя root-оболочку.Сначала был проведён базовый тест на сбой, чтобы доказать существование уязвимости, не превращая её в полноценный эксплойт.

Затем полный скрипт Worawit exploit_nss.py был выполнен против уязвимого бинарного файла.

Для проверки официального исправления тот же самый триггер PoC был выполнен против пропатченного бинарного файла Sudo.
sudoedit -s '\' 2>&1 | grep -q "sudoedit:" && echo "Vulnerable" || echo "Not vulnerable"

Sudo — стандартная административная программа, используемая на наших серверах, — содержит критический изъян в обработке текстовых входных данных, содержащих обратные слеши. Аккуратно отправив некорректно сформированную команду, злоумышленник с базовым доступом пользователя может обмануть систему, заставив её записать данные за пределами выделенной области памяти. Эта ошибка позволяет полностью обойти меры безопасности и получить полный несанкционированный административный контроль над машиной даже без необходимости вводить пароль.
Трудности: Одной из основных трудностей была хрупкость манипуляции кучей. Эксплойт-нагрузки, нацеленные на конкретные версии ОС, часто не срабатывают на других, поскольку базовая стандартная библиотека C (glibc) управляет блоками памяти по-разному. Чтобы успешно превратить эту уязвимость в полноценный эксплойт, требовалось точное понимание выравнивания памяти и раскладки переменных окружения (Heap Feng Shui), характерных для целевой среды.
Извлечённые уроки: С точки зрения защиты и операций безопасности, этот глубокий анализ подтвердил несколько ключевых концепций:
sudoedit -s, заканчивающихся escape-символами, мог бы позволить команде SOC обнаруживать попытки эксплуатации до того, как патч будет полностью развёрнут в инфраструктуре.Параллельный CVE: CVE-2019-14287 (обход безопасности Sudo)
Ещё одна известная уязвимость в той же самой кодовой базе Sudo имеет схожий паттерн первопричины: некорректный разбор и проверка пользовательского ввода. В CVE-2019-14287 логический изъян в том, как Sudo разбирал идентификатор пользователя (UID), позволял злоумышленнику выполнять команды с правами root, указав идентификатор пользователя -1 или 4294967295.
Параллель: Хотя Baron Samedit (CVE-2021-3156) — это изъян повреждения памяти, а CVE-2019-14287 — обход авторизации, первопричина в обоих случаях — сбой в начальной логике разбора аргументов. Обе уязвимости проистекают из того, что Sudo ошибочно доверяет и некорректно обрабатывает пограничные аргументы командной строки (завершающие обратные слеши против неожиданного целочисленного переноса) перед выполнением своих основных привилегированных функций.
Заявление о безопасности и этике: Все действия по эксплуатации и тестированию, продемонстрированные в этом отчёте, выполнялись исключительно в изолированной авторизованной локальной виртуальной машине. В ходе этого упражнения не затрагивались и не использовались продакшн-системы или несанкционированные сети.