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

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

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

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

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

Категории

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

CVE-2021-3560

Углублённый анализ CVE-2021-3560 — локальной уязвимости повышения привилегий в Linux PolKit. Включает анализ первопричины, механику эксплойта и демонстрацию состояния гонки, приводящего к получению root-доступа.

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

Популярное

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

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

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

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

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

CVE-2021-3560 PolKit: анализ локального повышения привилегий через гонку состояний

[toc]

Обзор уязвимости

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

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

Уязвимый продукт: linux PolKit (polkitd)

Затронутые версии: внедрена в исходном коде 0.113; https://www.venustech.com.cn/new_type/aqtg/20210611/22788.html

  • RHEL 8
  • Fedora 21 и выше
  • Debian testing (“bullseye”)
  • Ubuntu 20.04

Условия эксплуатации: локальный доступ к linux; наличие dbus + polkitd

Результат эксплуатации: локальное повышение привилегий

Получение исходного кода:

  • polkit-0.113: https://launchpad.net/debian/+source/policykit-1/0.113-5
  • accountsservice: apt source accountsservice
  • dbus: apt source dbus

Настройка окружения

Стандартного образа ubuntu-20.04.2 достаточно для воспроизведения: http://old-releases.ubuntu.com/releases/20.04.2/ubuntu-20.04.2-desktop-amd64.iso

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

Место возникновения уязвимости

Сначала посмотрим на проблемный код

/polkit-0.113/src/polkit/polkitsystembusname.c : 388 : polkit_system_bus_name_get_creds_sync

static void
on_retrieved_unix_uid_pid (GObject              *src,
			   GAsyncResult         *res,
			   gpointer              user_data)
{
  AsyncGetBusNameCredsData *data = user_data;
  GVariant *v;

  v = g_dbus_connection_call_finish ((GDBusConnection*)src, res,
				     data->caught_error ? NULL : data->error);
  if (!v)
    {
      data->caught_error = TRUE; //某些原因失败之后设置error位
    }
  else
  {
      ··· ···//执行成功的数据处理
  }
  ··· ···
}

static gboolean
polkit_system_bus_name_get_creds_sync (PolkitSystemBusName           *system_bus_name,
				       guint32                       *out_uid,
				       guint32                       *out_pid,
				       GCancellable                  *cancellable,
				       GError                       **error)
{
  gboolean ret = FALSE;
  AsyncGetBusNameCredsData data = { 0, }; //data 被初始化为0
  ··· ···
  g_dbus_connection_call (connection,
			  "org.freedesktop.DBus",       /* name */
			  "/org/freedesktop/DBus",      /* object path */
			  "org.freedesktop.DBus",       /* interface name */
			  "GetConnectionUnixUser",      /* method */
			  g_variant_new ("(s)", system_bus_name->name),
			  G_VARIANT_TYPE ("(u)"),
			  G_DBUS_CALL_FLAGS_NONE,
			  -1,
			  cancellable,
			  on_retrieved_unix_uid_pid, //回调函数
			  &data);
  g_dbus_connection_call (connection,
			  "org.freedesktop.DBus",       /* name */
			  "/org/freedesktop/DBus",      /* object path */
			  "org.freedesktop.DBus",       /* interface name */
			  "GetConnectionUnixProcessID", /* method */
			  g_variant_new ("(s)", system_bus_name->name),
			  G_VARIANT_TYPE ("(u)"),
			  G_DBUS_CALL_FLAGS_NONE,
			  -1,
			  cancellable,
			  on_retrieved_unix_uid_pid, //回调函数
			  &data);

  while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error))
    g_main_context_iteration (tmp_context, TRUE); //等待总线那边执行完毕,uid、pid都处理完毕或异常

  if (out_uid)
    *out_uid = data.uid;
  if (out_pid)
    *out_pid = data.pid;
  ret = TRUE; //无论如何都是 TRUE?
 out:
  if (tmp_context)
    {
      g_main_context_pop_thread_default (tmp_context);
      g_main_context_unref (tmp_context);
    }
  if (connection != NULL)
    g_object_unref (connection);
  return ret;
}

В функции polkit_system_bus_name_get_creds_sync выполняется аутентификация некоторых запросов (конкретный логический сценарий будет подробно описан ниже). Сначала через шину org.freedesktop.DBus вызываются методы GetConnectionUnixUser и GetConnectionUnixProcessID; эти методы предоставляются шиной org.freedesktop.DBus и служат для получения PID и UID пользователя запрашивающего процесса, после чего данные передаются в callback-функцию on_retrieved_unix_uid_pid для обработки. Затем выполняется блокирующее ожидание завершения выполнения процесса на стороне шины.

В функции on_retrieved_unix_uid_pid видно, что в зависимости от результата выполнения на стороне шины устанавливается признак ошибки (error?), после чего устанавливается бит ошибки; при успешном выполнении возвращаются UID пользователя или PID процесса. Однако в функции polkit_system_bus_name_get_creds_sync после блокирующего ожидания результата от шины (условием завершения обработки является обработка и UID, и PID, либо возникновение ошибки). То есть, с логической точки зрения, со стороны шины возможны три результата: получен UID пользователя 0 — привилегированный пользователь; получен UID пользователя, отличный от 0, — обычный пользователь; ошибка. Но в дальнейшей обработке ошибка не обрабатывается: out_uid, возвращаемый на верхний уровень, напрямую устанавливается в data.uid, полученный от шины, а затем ret просто устанавливается в TRUE:

  while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error))
    g_main_context_iteration (tmp_context, TRUE); //等待总线那边执行完毕,uid、pid都处理完毕或异常

  if (out_uid)
    *out_uid = data.uid;
  if (out_pid)
    *out_pid = data.pid;
  ret = TRUE; //无论如何都是 TRUE?

Однако был упущен случай, когда на стороне шины DBUS возникает ошибка выполнения: callback-функция устанавливает бит ошибки и возвращается, так и не обработав данные data, а data инициализируется нулём. В результате далее out_uid устанавливается в 0, то есть в привилегированного пользователя.

Где же используется эта проблемная функция polkit_system_bus_name_get_creds_sync?

Путь срабатывания

Процессом, в котором находится уязвимость, является polkitd:

polkit — это набор инструментов прикладного уровня, который, определяя и проверяя правила прав доступа, обеспечивает взаимодействие между процессами с разными приоритетами: управление решениями централизовано в единой среде и определяет, имеет ли процесс с низким приоритетом право доступа к процессу с высоким приоритетом.

Проще говоря, это фоновый процесс root, который посредством межпроцессного взаимодействия выполняет проверку прав, когда другие процессы с низкими привилегиями обращаются к функциям, предоставляемым процессами с высокими привилегиями. Поскольку при подключении gdb этот процесс перезапускается, анализ можно проводить только на уровне исходного кода, чтобы найти путь срабатывания уязвимой функции:

В polkitd для разработки широко используется фреймворк межпроцессного взаимодействия gio DBUS; можно заранее ознакомиться с руководством, обратив внимание на некоторые ключевые функции.

Далее проанализируем путь срабатывания уязвимости в polkitd:

  1. Сначала main:

    polkit-0.113\src\polkitbackend\polkitd.c : 155 : main

    int
    main (int    argc,
          char **argv)
    {
      ··· ···
      ··· ···
    
      loop = g_main_loop_new (NULL, FALSE);
    
      sigint_id = g_unix_signal_add (SIGINT,
                                     on_sigint,
                                     NULL);
    
      name_owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
                                      "org.freedesktop.PolicyKit1",  //注册了一个总线名称
                                      G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
                                        (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
                                      on_bus_acquired, //访问该总线时的回调函数
                                      on_name_acquired,
                                      on_name_lost,
                                      NULL,
                                      NULL);
    
      g_print ("Entering main event loop\n");
      g_main_loop_run (loop); //循环启动
      ··· ···
      ··· ···
    }
    
  2. Сначала регистрируется шина org.freedesktop.PolicyKit1, затем есть три callback-функции; основное внимание стоит уделить on_bus_acquired, которая вызывается при обращении к шине.

  3. В функции on_bus_acquired напрямую вызывается функция регистрации polkit_backend_authority_register

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