
# Эксплойт для CVE-2026-41651 PoC-эксплойт для CVE-2026-41651 — локального повышения привилегий TOCTOU в PackageKit, с техническим анализом, логикой обнаружения и рекомендациями по устранению уязвимости.
Классификация: Артефакт оценки Purple Team
Только для авторизованного использования. Этот документ и прилагаемый тестовый скрипт предназначены исключительно для внутренней проверки безопасности на системах, где получено письменное разрешение.

| Поле | Значение |
|---|---|
| ID CVE | CVE-2026-41651 |
| CWE | CWE-367 — Гонка «проверка-по-времени-использование-по-времени» (TOCTOU) |
| Компонент | PackageKit (packagekitd, служба D-Bus) |
| Затронуты | PackageKit ≤ 1.3.4 |
| Исправлено в | PackageKit 1.3.5 |
| Воздействие | Локальное повышение привилегий → root |
| Вектор атаки | Локальный / D-Bus (сеанс непривилегированного пользователя) |
| Раскрыто | 2026-04-22 (Deutsche Telekom Red Team) |
| Консультация | GHSA-f55j-vvr9-69xv |
| Коммит исправления | 76cfb675fb31acc3ad5595d4380bfff56d2a8697 |
PackageKit — это уровень абстракции D-Bus для системного управления пакетами, присутствующий по умолчанию на GNOME-десктопах в Debian, Ubuntu, Fedora, RHEL, SUSE и Arch Linux. Поскольку он опосредует привилегированные операции с пакетами от имени непривилегированных пользователей, ошибка в его потоке авторизации имеет системное воздействие уровня root.
pk-transaction.c (до версии 1.3.5) не обеспечивал защиту состояния при повторном вызове методов действий. Клиент D-Bus мог вызывать InstallFiles (или другие методы действий) несколько раз на одном и том же объекте транзакции после того, как он уже перешёл из состояния PK_TRANSACTION_STATE_NEW.
Атакующий (непривилегированный)
│
├─① CreateTransaction() → PackageKit возвращает путь объекта транзакции (tid)
│
├─② InstallFiles(tid, FLAG_SIMULATE=4, [dummy.pkg])
│ PackageKit ставит в очередь проверку авторизации polkit для dummy.pkg.
│ Установка ещё не происходит — SIMULATE означает только пробный запуск.
│
├─③ InstallFiles(tid, FLAG_NONE=0, [payload.pkg]) ← окно TOCTOU
│ Повторный вызов на том же tid до разрешения авторизации.
│ Уязвимые версии перезаписывают поставленные в очередь параметры на payload.pkg.
│
└─④ polkit предоставляет авторизацию (пользователь одобрил или авто-авторизация)
packagekitd устанавливает payload.pkg от имени root.
postinst/post-скрипт payload: install -m 4755 /bin/bash /tmp/.suid_bash
Атакующий выполняет /tmp/.suid_bash -p → root-оболочка.
Шаги ② и ③ отправляются как неблокирующие асинхронные вызовы D-Bus по одному соединению и сбрасываются одним записывающим вызовом. Два сообщения достигают packagekitd до того, как он сможет обработать ② и продвинуть конечный автомат, оставляя окно TOCTOU открытым. Исправление в 1.3.5 добавляет явную проверку состояния, которая возвращает PK_TRANSACTION_ERROR_INVALID_STATE при любом повторном вызове после PK_TRANSACTION_STATE_NEW.
Файл: cve-2026-41651-purpleteam.py
Язык: Python 3
Зависимости: python3-gi (интроспекция GObject / привязки GLib/Gio)
Демонстрирует эксплуатируемость CVE-2026-41651 на подготовленной тестовой системе с целью:
| Фаза | Действие |
|---|---|
| Подготовка | Проверяет /proc/mounts для выбора каталога с SUID/exec-возможностями, устанавливает umask(022), применяет явный chmod ко всем артефактам сборки, затем собирает фиктивный и полезный пакеты в /tmp |
| Эксплуатация | Открывает системное соединение D-Bus, создаёт транзакцию PackageKit, запускает гонку из двух вызовов |
| Полезная нагрузка | Пост-установочный скрипт пакета копирует /bin/bash в <drop_dir>/.suid_bash с режимом 04755, владелец root. Каталог сброса определяется во время выполнения (см. Поддержка усиленных сред) |
| Повышение | Ожидает появления SUID-бинарника (таймаут 90 с), затем выполняет execl в него с -p для получения root-оболочки |
| Очистка | Удаляет временные файлы .deb/.rpm при выходе (успех или неудача) |
Системы с усиленной защитой по умолчанию могут блокировать эксплойт в двух независимых точках. Скрипт обрабатывает обе автоматически.
027 / 077)Унаследованный от процесса umask 027 или 077 приводит к тому, что mkdir() создаёт каталоги с правами 750 или 700. И dpkg-deb, и rpmbuild должны пройти по всему дереву сборки — если какой-либо каталог недоступен для чтения, сборка молча завершается неудачей.
Применяемое исправление: os.umask(0o022) вызывается при запуске до создания любых файлов или каталогов. Кроме того, каждый каталог и файл в дереве сборки получает явный chmod сразу после создания (0o755 для каталогов и скриптов, 0o644 для файлов данных), поэтому правильные права гарантированы независимо от унаследованного umask.
nosuid / noexec на /tmp| Флаг | Влияние на эксплойт |
|---|---|
nosuid | Ядро молча снимает бит SUID с любого файла, хранящегося на этой файловой системе — скопированный bash никогда не становится root |
noexec | SUID-бинарник вообще не может быть выполнен |
Применяемое исправление: При запуске _find_suid_dir() читает /proc/mounts и проверяет каталоги-кандидаты в порядке предпочтения, пока не найдёт файловую систему без обоих флагов. Разрешённый путь затем встраивается в пост-установочный скрипт полезной нагрузки и используется для опроса и выполнения.