Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2021-3560 — Analyse approfondie de CVE-2021-3560, une vulnérabilité d'élévation de privilèges locale dans PolKit sous Linux. Comprend l'analyse de la cause racine, les mécanismes de l'exploit et une démonstration de la condition de course menant à l'accès root. | Kitploit
Outils/GitHubGitHub/chenaotian/cve-2021-3560
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationAnalyse de BinairesApprentissage et Éducation
GitHubchenaotian/cve-2021-3560

CVE-2021-3560

Analyse approfondie de CVE-2021-3560, une vulnérabilité d'élévation de privilèges locale dans PolKit sous Linux. Comprend l'analyse de la cause racine, les mécanismes de l'exploit et une démonstration de la condition de course menant à l'accès root.

Voir le dépôt
936il y a 4 ansPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Analyse de l'élévation de privilèges locale par condition de concurrence CVE-2021-3560 dans PolKit

[toc]

Résumé de la vulnérabilité

Identifiant de vulnérabilité : CVE-2021-3560

Score de vulnérabilité :

Produit vulnérable : linux PolKit (polkitd)

Périmètre impacté : introduit à partir du code source 0.113 ; https://www.venustech.com.cn/new_type/aqtg/20210611/22788.html

  • RHEL 8
  • Fedora 21 et versions ultérieures
  • Debian testing (« bullseye »)
  • Ubuntu 20.04

Conditions d'exploitation : linux local ; dbus + polkitd présents

Effet de l'exploitation : élévation de privilèges locale

Obtention du code source :

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

Mise en place de l'environnement

L'image Ubuntu par défaut ubuntu-20.04.2 peut être répliquée : http://old-releases.ubuntu.com/releases/20.04.2/ubuntu-20.04.2-desktop-amd64.iso

Principe de la vulnérabilité

Point de déclenchement

Regardons d'abord le code en cause

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

Dans la fonction polkit_system_bus_name_get_creds_sync , celle-ci effectue l'authentification de certaines requêtes (nous détaillerons le scénario logique plus loin). Elle appelle successivement les méthodes GetConnectionUnixUser et GetConnectionUnixProcessID via le bus org.freedesktop.DBus . Ces deux méthodes, fournies par le bus org.freedesktop.DBus , récupèrent le PID et l'UID de l'utilisateur du processus demandeur, puis les transmettent à la fonction de rappel on_retrieved_unix_uid_pid pour traiter les données retournées. Ensuite, elle bloque en attendant la fin de l'exécution du processus côté bus.

On peut voir dans la fonction on_retrieved_unix_uid_pid que, selon le résultat renvoyé par le bus, elle définit si une erreur s'est produite (error ?) puis positionne le drapeau d'erreur. Si l'exécution réussit, elle retourne normalement l'UID de l'utilisateur ou le PID du processus. Mais dans la fonction polkit_system_bus_name_get_creds_sync , après avoir bloqué en attendant le retour du bus (la condition de traitement terminé est que l'UID et le PID soient tous deux traités ou qu'une erreur se soit produite). Cela signifie qu'il y a logiquement trois résultats possibles du côté bus : récupération de l'UID 0 (utilisateur privilégié) ; récupération d'un UID non nul (utilisateur normal) ; erreur. Mais dans le traitement ultérieur, il n'y a pas de gestion d'erreur : on définit directement out_uid (destiné à l'étage supérieur) avec la valeur data.uid retournée par le bus, puis on met directement 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?

Mais on oublie un cas : l'exécution anormale du côté du bus DBUS, qui amène la fonction de rappel à positionner le drapeau d'erreur et à revenir sans traiter les données data. Comme data est initialisé à 0, cela conduit ensuite à définir out_uid à 0, c'est-à-dire utilisateur privilégié.

Alors, où est utilisée cette fonction défectueuse polkit_system_bus_name_get_creds_sync ?

Chemin de déclenchement

Le processus vulnérable est le processus polkitd :

polkit est un ensemble d'outils au niveau applicatif qui, en définissant et en auditant des règles d'autorisation, permet la communication entre processus de différentes priorités : la décision de contrôle est centralisée dans un cadre unifié, déterminant si un processus de basse priorité a le droit d'accéder à un processus de haute priorité.

En bref, il s'agit d'un processus root s'exécutant en arrière‑plan qui, via la communication inter‑processus, effectue un jugement d'autorisation lorsque d'autres processus de faible privilège accèdent aux fonctionnalités fournies par des processus de haut privilège. Comme attacher ce processus avec gdb le fait redémarrer, nous devons analyser le chemin de déclenchement de la fonction vulnérable à partir du code source :

polkitd utilise massivement le framework de communication inter‑processus gio DBUS. Vous pouvez consulter le manuel au préalable pour vous familiariser avec certaines fonctions importantes.

Analysons maintenant le chemin de déclenchement de la vulnérabilité dans polkitd :

  1. D'abord le 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); //循环启动
      ··· ···
      ··· ···
    }
    
Télécharger l’outil