Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2021-4034 — Подробное описание и эксплойт для доказательства концепции для CVE-2021-4034 (PolKit pkexec локальное повышение привилегий), включая среду лаборатории Docker для практического анализа и отладки. | Kitploit
Инструменты/GitHubGitHub/chenaotian/cve-2021-4034
Повышение привилегийАнализ уязвимостейЭксплуатацияТестирование на ПроникновениеОбучение и ОбразованиеЭксплуатация Бинарных ФайловЛаборатории и Практика
GitHubchenaotian/cve-2021-4034

CVE-2021-4034

Подробное описание и эксплойт для доказательства концепции для CVE-2021-4034 (PolKit pkexec локальное повышение привилегий), включая среду лаборатории Docker для практического анализа и отладки.

Репозиторий
123164 лет назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2021-4034 Анализ локального повышения привилегий PolKit

[toc]

Краткое описание уязвимости

Идентификатор уязвимости: CVE-2021-4034

Оценка уязвимости:

Продукт: linux PolKit (pkexec)

Затрагиваемые версии: версии с 2009 года по настоящее время (текущая 0.105) Ссылка: http://its.dlut.edu.cn/info/1054/78309.htm

Условия эксплуатации: локальный доступ в Linux; pkexec — SUID-файл с правами на выполнение

Получение исходного кода: apt source policykit-1 или https://launchpad.net/ubuntu/bionic/+package/policykit-1

Среда Docker

Среда Docker: chenaotian/cve-2021-4034

Мой собственный Docker-образ предоставляет:

  1. pkexec, скомпилированный с возможностью отладки по исходному коду
  2. glibc с отладочными символами (похоже, бесполезно)
  3. gdb и плагины gdb pwngdb & pwndbg (похоже, необязательно)
  4. Эксплойты в отладочной среде

Всё находится в каталоге /root/:

image-20220126183638493

  • Каталог exp содержит файлы exp и run.sh; можно переключиться на пользователя test командой su test и запустить
  • glibc-2.27 — каталог исходного кода glibc, скорее всего не понадобится, но пригодится для отладки исходного кода в gdb
  • polkit-0.105 — исходный пакет policykit

Запуск Docker:

docker run -d -ti --rm -h cvedebug --name cvedebug --cap-add=SYS_PTRACE chenaotian/cve-2021-4034:latest /bin/bash

Тестирование эксплойта:

cd ~/exp/CVE-2021-4034/
./run.sh
su test
./exp
whoami

Принцип уязвимости

Уязвимость затрагивает команду pkexec из пакета polkit. pkexec похож на sudo — это инструмент, позволяющий выполнять команды от имени другого пользователя (обычно root). С помощью команды dpkg можно узнать, к какому пакету принадлежит pkexec:

dpkg -S /usr/bin/pkexec

image-20220126152839307

Затем можно получить исходный пакет (он также есть в моём Docker-образе) и скомпилировать отладочную версию для удобства анализа.

Точка срабатывания уязвимости

/polkit-0.105/src/programs/pkexec.c : 386 main

int
main (int argc, char *argv[])
{
    
  ··· ···
  ··· ···
      
  /* 这段的意思就是,循环遍历用户输入参数,根据输入的不同参数设置值
   * 但问题在于,他循环遍历的起点是1,没有考虑用户没有输入任何参数的情况
   */
  for (n = 1; n < (guint) argc; n++) 
    {
      if (strcmp (argv[n], "--help") == 0)
        {
          opt_show_help = TRUE;
        }
      ··· ···
      else //如果是无法识别的参数则跳出循环,这里意味着该参数是想要执行的命令
        {
          break;
        }
    }

  ··· ···

  g_assert (argv[argc] == NULL);
  path = g_strdup (argv[n]); //获取执行命令具体字符串
  if (path == NULL)
    {
      ···
    }
  if (path[0] != '/')
    {
      /* g_find_program_in_path() is not suspectible to attacks via the environment */
      //该函数会根据PATH环境变量寻找要执行命令的绝对地址
      s = g_find_program_in_path (path); 
      if (s == NULL)
        {
          ···
        }
      g_free (path);
      argv[n] = path = s;//把获取到的绝对地址修改回命令行参数
    }
  ··· ···
  ··· ···

Анализ на основе комментариев в коде:

  1. В функции main выполняется установка переменных на основе аргументов командной строки. Однако цикл for начинается с 1, то есть подразумевается, что передан хотя бы один аргумент (команда, которую нужно выполнить через pkexec).
  2. Если найден аргумент, не начинающийся с --, он считается командой для выполнения. Цикл прерывается, и выполняется дальнейшая логика.
  3. Вызывается функция g_find_program_in_path, которая ищет абсолютный путь к команде в переменной PATH. Например, для cat вернёт /bin/cat.
  4. Полученный абсолютный путь записывается обратно в массив аргументов (то есть команда заменяется полным путём к файлу).

Всё понятно, но проблема в следующем:

  1. При запуске двоичного файла Linux аргументы командной строки argv[] и переменные окружения environ[] помещаются в нижнюю часть стека, причём они расположены последовательно. Последний элемент argv[] равен null.

    image-20220126162140802

  2. Если pkexec запускается из командной строки без дополнительных аргументов, то argv[0] равен "pkexec", а argv[1] равен \x00. Всё нормально. Но если pkexec запускается с помощью execve без дополнительных аргументов, то argv[0] равен \x00, и argv[1] указывает на первую переменную окружения! При чтении argv[1] происходит выход за границы массива — читается environ[0].

    При запуске pkexec из командной строки argc равно 1, argv[0] — путь к pkexec:

    image-20220126162616203

    При запуске pkexec с помощью execve argc равно 0:

    image-20220126162804529

К чему это приводит? Когда execve запускается без аргументов, длина argv[] равна 0, и argv[1] указывает на environ[0]. Таким образом, описанная выше логика превращается в: взять значение первой переменной окружения и найти её абсолютный путь в PATH. Если найден, записать обратно в первую переменную окружения. Тогда способ эксплуатации выглядит следующим образом:

Эксплуатация уязвимости

Сначала важно отметить, что pkexec — это привилегированный файл (suid):

image-20220126161324831

Как использовать переменные окружения в привилегированном файле? Сначала разберём одну деталь:

Одна деталь

Динамический компоновщик Linux ld-linux-x86-64.so.2 очищает конфиденциальные переменные окружения при выполнении привилегированной программы:

void
_dl_non_dynamic_init (void)
{
  ··· ···
  ··· ···

  if (__libc_enable_secure) //特权模式的情况下
    {
      static const char unsecure_envvars[] =
	UNSECURE_ENVVARS
#ifdef EXTRA_UNSECURE_ENVVARS
	EXTRA_UNSECURE_ENVVARS
#endif
	;
      const char *cp = unsecure_envvars;

      //循环将危险环境变量列表中的环境变量全部清空(unset)
      while (cp < unsecure_envvars + sizeof (unsecure_envvars)) 
	{
	  __unsetenv (cp);
	  cp = (const char *) __rawmemchr (cp, '\0') + 1;
	}

#if !HAVE_TUNABLES
      if (__access ("/etc/suid-debug", F_OK) != 0)
	__unsetenv ("MALLOC_CHECK_");
#endif
    }
··· ···
··· ···
}

Список опасных переменных окружения UNSECURE_ENVVARS определён следующим образом:

#define GLIBC_TUNABLES_ENVVAR "GLIBC_TUNABLES\0"
#define UNSECURE_ENVVARS \
  "GCONV_PATH\0"							      \
  "GETCONF_DIR\0"							      \
  GLIBC_TUNABLES_ENVVAR							      \
  "HOSTALIASES\0"							      \
  "LD_AUDIT\0"								      \
  "LD_DEBUG\0"								      \
  "LD_DEBUG_OUTPUT\0"							      \
  "LD_DYNAMIC_WEAK\0"							      \
  "LD_HWCAP_MASK\0"							      \
  "LD_LIBRARY_PATH\0"							      \
  "LD_ORIGIN_PATH\0"							      \
  "LD_PRELOAD\0"							      \
  "LD_PROFILE\0"							      \
  "LD_SHOW_AUXV\0"							      \
  "LD_USE_LOAD_BIAS\0"							      \
  "LOCALDOMAIN\0"							      \
  "LOCPATH\0"								      \
  "MALLOC_TRACE\0"							      \
  "NIS_PATH\0"								      \
  "NLSPATH\0"								      \
  "RESOLV_HOST_CONF\0"							      \
  "RES_OPTIONS\0"							      \
  "TMPDIR\0"								      \
  "TZDIR\0"

Когда программа обнаруживает, что является привилегированной (suid), она очищает эти переменные. Как видно, большинство из них относятся к серии LD_, которые могут указывать пути загрузки динамических библиотек. Это предотвращает загрузку suid-программой недоверенных .so через эти переменные, что могло бы привести к выполнению вредоносного кода и повышению привилегий.

Скачать инструмент