Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2021-3560 — Análisis en profundidad de CVE-2021-3560, una vulnerabilidad de escalada de privilegios local en PolKit de Linux. Incluye análisis de la causa raíz, mecánica del exploit y una demostración de la condición de carrera que conduce al acceso root. | Kitploit
Herramientas/GitHubGitHub/chenaotian/cve-2021-3560
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónAnálisis de BinariosAprendizaje y Educación
GitHubchenaotian/cve-2021-3560

CVE-2021-3560

Análisis en profundidad de CVE-2021-3560, una vulnerabilidad de escalada de privilegios local en PolKit de Linux. Incluye análisis de la causa raíz, mecánica del exploit y una demostración de la condición de carrera que conduce al acceso root.

Ver Repositorio
936hace 4 añosAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2021-3560 Análisis de escalada de privilegios local por condición de carrera en PolKit

[toc]

Resumen de la vulnerabilidad

Identificador de vulnerabilidad: CVE-2021-3560

Puntuación de vulnerabilidad:

Producto vulnerable: linux PolKit (polkitd)

Alcance afectado: introducido en el código fuente 0.113; https://www.venustech.com.cn/new_type/aqtg/20210611/22788.html

  • RHEL 8
  • Fedora 21 y versiones posteriores
  • Debian testing ("bullseye")
  • Ubuntu 20.04

Requisitos de explotación: local en Linux; presencia de dbus + polkitd

Impacto: escalada de privilegios local

Obtención del código fuente:

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

Configuración del entorno

La imagen predeterminada de ubuntu-20.04.2 es suficiente para reproducir el problema: http://old-releases.ubuntu.com/releases/20.04.2/ubuntu-20.04.2-desktop-amd64.iso

Principio de la vulnerabilidad

Punto donde ocurre la vulnerabilidad

Primero veamos el código del problema

/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;
}

En la función polkit_system_bus_name_get_creds_sync, dicha función autentica ciertas solicitudes (el escenario lógico específico se detallará más adelante). Primero se invocan los métodos GetConnectionUnixUser y GetConnectionUnixProcessID a través del bus org.freedesktop.DBus. Estos dos métodos son proporcionados por el bus org.freedesktop.DBus y obtienen el PID del proceso solicitante y el UID del usuario; luego se pasan a la función de callback on_retrieved_unix_uid_pid para procesar los datos devueltos. Después se bloquea esperando a que el proceso del bus complete su ejecución.

Se puede observar en la función on_retrieved_unix_uid_pid que, según el resultado devuelto por el bus, se establece si ocurrió un error (¿error?) y luego se activa el bit de error. Si la ejecución es exitosa, simplemente devuelve el UID del usuario o el PID del proceso. Pero en la función polkit_system_bus_name_get_creds_sync, después de bloquear esperando el resultado del bus (el criterio de finalización es que tanto el UID como el PID hayan sido procesados o que haya ocurrido una excepción). Es decir, lógicamente hay tres resultados posibles de vuelta del bus: se obtiene un UID de usuario 0 (usuario privilegiado); se obtiene un UID de usuario distinto de 0 (usuario normal); o una excepción. Pero en el procesamiento posterior no se maneja la excepción: out_uid, que se va a devolver a la capa superior, se establece directamente al data.uid devuelto por el bus, y luego ret se establece directamente en 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?

Pero se ignora un caso: cuando el bus DBUS falla, la función de callback establece el bit de excepción y regresa sin procesar los datos data. Como data se inicializa a 0, esto hace que posteriormente out_uid se establezca directamente a 0, es decir, un usuario privilegiado.

Entonces, ¿dónde se utiliza esta función problemática polkit_system_bus_name_get_creds_sync?

Ruta de activación

El proceso donde reside la vulnerabilidad es el proceso polkitd:

polkit es un conjunto de herramientas a nivel de aplicación que, mediante la definición y revisión de reglas de permisos, permite la comunicación entre procesos de diferentes prioridades: las decisiones de control se centralizan en un marco unificado que determina si un proceso de baja prioridad tiene derecho a acceder a un proceso de alta prioridad.

En resumen, es un proceso root que se ejecuta en segundo plano y, mediante comunicación entre procesos, toma decisiones de permisos cuando otros procesos de bajos privilegios acceden a funcionalidades ofrecidas por procesos de altos privilegios. Como este proceso se reinicia si se adjunta gdb, solo podemos analizarlo a nivel de código fuente para encontrar la ruta de activación de la función vulnerable:

polkitd se desarrolla utilizando ampliamente el framework de comunicación entre procesos gio DBUS. Puede consultar previamente el manual y prestar atención a algunas funciones clave.

A continuación, analizamos la ruta de activación de la vulnerabilidad en polkitd:

  1. Primero, el 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. Primero se registra un bus llamado org.freedesktop.PolicyKit1, y luego hay tres callbacks; el principal es on_bus_acquired, que se invoca cuando se accede al bus.

Descargar herramienta