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-4034 — Analyse détaillée et preuve de concept d'exploitation pour CVE-2021-4034 (élévation de privilèges locale PolKit pkexec), incluant un environnement de laboratoire Docker pour une analyse et un débogage pratiques. | Kitploit
Outils/GitHubGitHub/chenaotian/cve-2021-4034
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationTests d'IntrusionApprentissage et ÉducationExploitation de BinairesLabs et Pratique
GitHubchenaotian/cve-2021-4034

CVE-2021-4034

Analyse détaillée et preuve de concept d'exploitation pour CVE-2021-4034 (élévation de privilèges locale PolKit pkexec), incluant un environnement de laboratoire Docker pour une analyse et un débogage pratiques.

Voir le dépôt
12316il 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 PolKit CVE-2021-4034

[toc]

Présentation de la vulnérabilité

Identifiant de la vulnérabilité : CVE-2021-4034

Score de la vulnérabilité :

Produit concerné : linux PolKit (pkexec)

Versions affectées : toutes les versions de 2009 à aujourd'hui (actuellement 0.105) Référence : http://its.dlut.edu.cn/info/1054/78309.htm

Conditions d'exploitation : linux local ; pkexec est un fichier suid avec droit d'exécution

Obtention du code source : apt source policykit-1

​ ou https://launchpad.net/ubuntu/bionic/+package/policykit-1

Environnement docker

Environnement docker : chenaotian/cve-2021-4034

J'ai monté moi-même ce docker, il fournit :

  1. Un pkexec compilé moi-même, débogable au niveau du code source
  2. Une glibc avec symboles de débogage (apparemment pas très utile)
  3. gdb et les plugins gdb pwngdb & pwndbg (apparemment pas nécessaires)
  4. L'exp dans l'environnement de débogage

Tout se trouve dans le répertoire /root/ :

image-20220126183638493

  • Le répertoire exp contient l'exp et run.sh, on peut passer à l'utilisateur test avec su test puis l'exécuter
  • glibc-2.27 est le répertoire du code source de glibc, probablement inutile, mais pratique pour le débogage source avec gdb si besoin
  • polkit-0.105 est le paquet source de policykit

Démarrage de docker :

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

Test de l'exp :

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

Principe de la vulnérabilité

Le produit concerné par la vulnérabilité est la commande pkexec de polkit. pkexec, comme sudo, est un outil qui nous permet d'exécuter des commandes en tant qu'un autre utilisateur (généralement root). La commande dpkg permet de voir le paquet auquel appartient pkexec :

dpkg -S /usr/bin/pkexec

image-20220126152839307

Ensuite, on récupère le paquet source (il est aussi présent dans mon docker), puis on compile à partir du paquet source une version débogable pour faciliter le débogage.

Point de déclenchement de la vulnérabilité

Le principe de déclenchement de la vulnérabilité est très simple

/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;//把获取到的绝对地址修改回命令行参数
    }
  ··· ···
  ··· ···

Selon l'analyse de mes commentaires dans le code :

  1. Tout d'abord, la fonction main définit certaines variables en fonction des arguments de la ligne de commande fournis par l'utilisateur, mais ici la boucle for commence à 1, ce qui signifie qu'elle suppose qu'au moins un argument est fourni (la commande à exécuter par pkexec)
  2. Si un argument de ligne de commande ne commençant pas par -- est rencontré, il est considéré comme la commande à exécuter avec pkexec, et on sort de la boucle pour passer à la logique suivante.
  3. La fonction g_find_program_in_path est appelée pour rechercher le chemin absolu de la commande. Cette fonction cherche le chemin absolu de l'argument (commande) passé en utilisant la variable d'environnement PATH. Par exemple, si cat est passé, elle renvoie /bin/cat.
  4. Le chemin absolu renvoyé est réécrit à la position de cet argument de ligne de commande. (On peut comprendre cela comme la conversion d'une commande en chemin absolu du fichier correspondant)

C'est assez facile à comprendre, mais le problème est le suivant :

  1. Lorsqu'un binaire Linux s'exécute, les arguments de ligne de commande argv[] et les variables d'environnement environ[] sont placés en bas de la pile, et argv[] et environ[] sont contigus. Le dernier élément de argv[] est null.

    image-20220126162140802

  2. Si pkexec est lancé depuis la ligne de commande sans aucun autre argument, alors argv[0] vaut "pkexec" et argv[1] vaut \x00, aucun problème. Mais si pkexec est lancé via la fonction execve sans aucun autre argument, alors argv[0] vaut \x00, et argv[1] pointe vers les variables d'environnement ! Lors de la lecture de argv[1], on lit hors limites environ[0].

    Lors d'un lancement direct de pkexec depuis la ligne de commande, argc vaut 1 et argv[0] est le chemin de pkexec :

    image-20220126162616203

    Avec la fonction execve pour lancer pkexec, argc vaut 0 :

    image-20220126162804529

Quel est alors l'impact ? Lors du lancement avec execve, sans aucun autre argument, la longueur de argv[] est 0, donc argv[1] correspond à environ[0]. La logique analysée ci-dessus devient alors : récupérer la valeur de la première variable d'environnement et rechercher son chemin absolu dans la variable PATH. S'il est trouvé, l'écrire dans la première variable d'environnement. La méthode d'exploitation est alors la suivante :

Exploitation de la vulnérabilité

Tout d'abord, il faut préciser que pkexec est un fichier privilégié (suid) :

image-20220126161324831

Comment utiliser les variables d'environnement dans un fichier privilégié pour faire quelque chose ? Commençons par comprendre un petit détail :

Un petit détail

Le linker dynamique de Linux ld-linux-x86-64.so.2 supprime les variables d'environnement sensibles lors de l'exécution d'un programme privilégié :

Fonction _dl_non_dynamic_init : glibc-2.27/elf/dl-support.c : 307

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
    }
··· ···
··· ···
}

La liste des variables d'environnement dangereuses UNSECURE_ENVVARS est définie comme suit :

glibc-2.27/sysdeps/generic/unsecvars.h : 10

Télécharger l’outil