Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2021-4034 — Ausführlicher Bericht und Proof-of-Concept-Exploit für CVE-2021-4034 (PolKit pkexec lokale Privilegieneskalation), einschließlich einer Docker-Lab-Umgebung für praktische Analyse und Debugging. | Kitploit
Tools/GitHubGitHub/chenaotian/cve-2021-4034
Privilege EscalationSchwachstellenanalyseExploitationPenetrationstestsLernen & BildungBinary-ExploitationLabs & Praxis
GitHubchenaotian/cve-2021-4034

CVE-2021-4034

Ausführlicher Bericht und Proof-of-Concept-Exploit für CVE-2021-4034 (PolKit pkexec lokale Privilegieneskalation), einschließlich einer Docker-Lab-Umgebung für praktische Analyse und Debugging.

Repository anzeigen
12322vor 4 JahrenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2021-4034 PolKit Lokale Privilegienausweitung Analyse

[toc]

Schwachstellenübersicht

Schwachstellennummer: CVE-2021-4034

Schwachstellenbewertung:

Schwachstellenprodukt: Linux PolKit (pkexec)

Betroffene Versionen: Betrifft Versionen von 2009 bis heute (aktuell 0.105) Referenz: http://its.dlut.edu.cn/info/1054/78309.htm

Ausnutzungsbedingungen: Linux lokaler Zugriff; pkexec ist eine suid-Datei und hat Ausführungsberechtigung

Quellcode-Bezug: apt source policykit-1 oder https://launchpad.net/ubuntu/bionic/+package/policykit-1

Docker-Umgebung

Docker-Umgebung: chenaotian/cve-2021-4034

Ich habe selbst einen Docker erstellt, der Folgendes bereitstellt:

  1. Ein selbst kompiliertes pkexec mit Quellcode-Debugging
  2. Glibc mit Debug-Symbolen (scheinbar nicht nützlich)
  3. GDB und GDB-Plugins pwngdb & pwndbg (scheinbar nicht notwendig)
  4. Das Exp in der Debug-Umgebung

Alles befindet sich im Verzeichnis /root/:

image-20220126183638493

  • Das Exp-Verzeichnis ist das Verzeichnis, in dem sich das Exp und die run.sh befinden. Mit su test kann man zum Test-Benutzer wechseln und es ausführen.
  • glibc-2.27 ist das Quellcode-Verzeichnis von glibc, wird wahrscheinlich nicht benötigt, aber falls nötig, erleichtert es das Debugging mit GDB.
  • polkit-0.105 ist das PolicyKit-Quellpaket

Docker starten:

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

Exp testen:

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

Schwachstellenprinzip

Das betroffene Produkt ist der Befehl pkexec von Polkit. pkexec ist ähnlich wie sudo ein Werkzeug, mit dem wir Befehle als anderer Benutzer (normalerweise root) ausführen können. Mit dem Befehl dpkg kann man das Paket anzeigen, zu dem pkexec gehört:

dpkg -S /usr/bin/pkexec

image-20220126152839307

Dann das Quellpaket beziehen (auch in meinem Docker enthalten) und anschließend aus dem Quellpaket selbst eine debug-fähige Version kompilieren, um das Debugging zu erleichtern.

Auslösepunkt der Schwachstelle

Das Prinzip der Schwachstellenauslösung ist sehr einfach.

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

int
main (int argc, char *argv[])
{
    
  ··· ···
  ··· ···
      
  /* Das bedeutet: Durchlaufe die Benutzereingabeparameter und setze Werte basierend auf den verschiedenen eingegebenen Parametern.
   * Das Problem ist jedoch, dass die Schleife bei 1 beginnt und den Fall nicht berücksichtigt, dass der Benutzer keine Parameter eingegeben hat.
   */
  for (n = 1; n < (guint) argc; n++) 
    {
      if (strcmp (argv[n], "--help") == 0)
        {
          opt_show_help = TRUE;
        }
      ··· ···
      else //Wenn ein unbekannter Parameter erkannt wird, die Schleife verlassen, was bedeutet, dass dieser Parameter der auszuführende Befehl ist
        {
          break;
        }
    }

  ··· ···

  g_assert (argv[argc] == NULL);
  path = g_strdup (argv[n]); //Hole die konkrete Zeichenkette des auszuführenden Befehls
  if (path == NULL)
    {
      ···
    }
  if (path[0] != '/')
    {
      /* g_find_program_in_path() ist nicht angreifbar durch Angriffe über die Umgebung */
      //Diese Funktion sucht nach dem absoluten Pfad des auszuführenden Befehls basierend auf der PATH-Umgebungsvariable.
      s = g_find_program_in_path (path); 
      if (s == NULL)
        {
          ···
        }
      g_free (path);
      argv[n] = path = s;//Setze den erhaltenen absoluten Pfad zurück in den Befehlszeilenparameter
    }
  ··· ···
  ··· ···

Basierend auf meinen Kommentaren im Code ergibt sich folgende Analyse:

  1. Zunächst werden in der main-Funktion einige Variablen basierend auf den vom Benutzer eingegebenen Befehlszeilenparametern gesetzt. Der Startwert der for-Schleife ist 1, was bedeutet, dass standardmäßig davon ausgegangen wird, dass mindestens ein Parameter vorhanden ist (der Befehl, der mit pkexec ausgeführt werden soll).
  2. Wenn ein Befehlszeilenparameter gefunden wird, der nicht mit -- beginnt, wird dieser als der auszuführende Befehl angesehen, und die Schleife wird verlassen, um mit der folgenden Logik fortzufahren.
  3. Die Funktion g_find_program_in_path wird aufgerufen, um den absoluten Pfad des Befehls zu suchen. g_find_program_in_path sucht basierend auf der PATH-Umgebungsvariable nach dem absoluten Pfad des übergebenen Parameters (Befehl). Zum Beispiel gibt die Eingabe von cat den Wert /bin/cat zurück.
  4. Der zurückgegebene absolute Pfad wird zurück in die Position des Befehlszeilenparameters geschrieben. (Kann man als Konvertierung vom Befehl zum absoluten Pfad der entsprechenden Datei verstehen.)

Das ist gut zu verstehen, aber das Problem liegt darin:

  1. Wenn ein Linux-Binärprogramm ausgeführt wird, werden die Befehlszeilenparameter argv[] und die Umgebungsvariablen environ[] am unteren Ende des Stacks abgelegt, und argv[] und environ[] sind miteinander verbunden. Das letzte Element von argv[] ist null.

    image-20220126162140802

  2. Wenn pkexec über die Befehlszeile gestartet wird und keine anderen Parameter übergeben werden, ist argv[0] gleich "pkexec" und argv[1] ist \x00 – kein Problem. Wenn pkexec jedoch mit der Funktion execve gestartet wird und keine weiteren Parameter übergeben werden, ist argv[0] gleich \x00 und argv[1] zeigt auf die Umgebungsvariablen! Wenn dann argv[1] gelesen wird, wird über die Grenzen auf environ[0] zugegriffen.

    Bei direktem Start von pkexec über die Befehlszeile ist argc gleich 1, argv[0] ist der Pfad von pkexec:

    image-20220126162616203

    Beim Start von pkexec mit der Funktion execve ist argc gleich 0:

    image-20220126162804529

Welche Auswirkungen hat das? Wenn execve ohne weitere Parameter verwendet wird, hat argv[] die Länge 0, und somit ist argv[1] gleich environ[0]. Dadurch wird die oben analysierte Logik zu: Hole den Wert der ersten Umgebungsvariable und suche im PATH-Umgebungsvariablen nach dessen absolutem Pfad. Falls gefunden, schreibe ihn zurück in die erste Umgebungsvariable. Die Ausnutzungsmethode ergibt sich wie folgt:

Schwachstellenausnutzung

Zuerst muss klar sein, dass pkexec eine privilegierte (suid) Datei ist:

image-20220126161324831

Wie kann man in einer privilegierten Datei mit Hilfe von Umgebungsvariablen etwas anstellen? Zunächst ein kleines Detail:

Ein kleines Detail

Der dynamische Linker von Linux, ld-linux-x86-64.so.2, löscht beim Ausführen eines privilegierten Programms sensible Umgebungsvariablen:

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

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

  if (__libc_enable_secure) //Im privilegierten Modus
    {
      static const char unsecure_envvars[] =
	UNSECURE_ENVVARS
#ifdef EXTRA_UNSECURE_ENVVARS
	EXTRA_UNSECURE_ENVVARS
#endif
	;
      const char *cp = unsecure_envvars;
Tool herunterladen