packagekitd от имени root. Для взаимодействия с PackageKit эксплойт использует D-Bus API библиотеки GLib, в частности метод
InstallFiles(), предназначенный для установки локальных deb/rpm-пакетов. Метод принимает набор флагов транзакции, определяющих её поведение. Часть флагов считается безопасной и может использоваться без полноценной авторизации. Например, флаг simulate выполняет только проверку зависимостей и не приводит к фактической установке ПО. Уязвимость связана с обработкой уже созданной транзакции. После первоначальной проверки безопасности PackageKit помечает транзакцию как безопасную, однако при последующем изменении её параметров повторная проверка не выполняется. Это создаёт TOCTOU condition: транзакция, созданная с флагом
simulate, может быть изменена на полноценную установку пакета с флагом none, при этом PackageKit считает авторизацию уже пройденной.PoC создаёт два локальных пакета: dummy-пакет и payload-пакет. Первый используется для прохождения проверки безопасности в режиме simulate. Второй содержит postinst payload, выполняемый в контексте packagekitd. В опубликованном PoC используется команда
install -m 4755 /bin/bash /tmp/.suid_bash
которая создаёт SUID-копию bash. После этого атакующий может получить root-доступ через запуск bash с аргументом -p.
Для эксплутации необходимо создать две транзакции через
g_dbus_connection_call(). Первая вызывает InstallFiles() для dummy-пакета с флагом simulate, который выглядит как g_variant_new("(u^as)", 4, ...). Вторая сразу переиспользует тот же объект транзакции, подменяя пакет на payload и устанавливая флаг полноценной установки: g_variant_new("(u^as)", 0, ...). После вызова g_dbus_connection_flush_sync() обе операции попадают в очередь обработки почти одновременно. В результате PackageKit выполняет установку второго пакета от имени root, несмотря на то, что авторизация была получена только для безопасной операции. Backend пакетного менеджера (dpkg/rpm) запускает postinst/preinst-скрипты payload-пакета с привилегиями root.
В Debian/Ubuntu это выглядит как:
/bin/sh /var/lib/dpkg/info/<package>.postinst configure
В RPM-системах:
/bin/sh /var/tmp/rpm-tmp.*
Постэксплуатация зависит от содержимого скрипта установки. Помимо создания SUID-shell могут использоваться: модификация /etc/shadow, добавление SSH-ключей, создание systemd unit-файлов, изменение PAM-конфигурации и другие механизмы закрепления.
Как защищаться:
Если нет возможности обновить PackageKit до пропатченной версии, детектируйте атаку по обращениям к PackageKit/GLib API или по цепочке процессов пакетного менеджера.
Для Debian-based систем индикатором может быть запуск postinst/preinst-скриптов из
/var/lib/dpkg/info/ с последующим вызовом chmod или install, выставляющими SUID/SGID-биты. Для RPM-based систем аналогичным индикатором является запуск временных скриптов
/var/tmp/rpm-tmp.*. Также полезно отслеживать инициаторов обращений к dpkg/rpm. Подозрительной может быть активность процессов
dpkg-deb и rpmbuild, запущенных не через стандартные средства управления пакетами (apt, apt-get, dpkg, rpm, dnf, yum, zypper, mock, koji). Дополнительным IoC могут выступать журнальные записи PackageKit о неуспешной аутентификации, возникающие в процессе эксплуатации уязвимости:
May 23 13:00:00 hostname PackageKit[PID]: uid 1000 is trying to obtain org.freedesktop.packagekit.package-install-untrusted auth (only_trusted:0)
May 23 13:00:01 hostname PackageKit[PID]: uid 1000 failed to obtain auth
