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.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2021-4034 — Análisis detallado y exploit de prueba de concepto para CVE-2021-4034 (escalada de privilegios local de PolKit pkexec), incluido un entorno de laboratorio Docker para análisis práctico y depuración. | Kitploit
Herramientas/GitHubGitHub/chenaotian/cve-2021-4034
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónPruebas de PenetraciónAprendizaje y EducaciónExplotación de BinariosLabs y Práctica
GitHubchenaotian/cve-2021-4034

CVE-2021-4034

Análisis detallado y exploit de prueba de concepto para CVE-2021-4034 (escalada de privilegios local de PolKit pkexec), incluido un entorno de laboratorio Docker para análisis práctico y depuración.

Ver Repositorio
12322hace 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

Análisis de Elevación de Privilegios Local CVE-2021-4034 (PolKit)

[toc]

Resumen de la vulnerabilidad

Identificador de vulnerabilidad: CVE-2021-4034

Puntuación de la vulnerabilidad:

Producto afectado: linux PolKit (pkexec)

Alcance: Afecta versiones desde 2009 hasta la actual (0.105). Referencia: http://its.dlut.edu.cn/info/1054/78309.htm

Condiciones de explotación: linux local; pkexec es un archivo suid y tiene permisos de ejecución.

Obtención del código fuente: apt source policykit-1

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

Entorno Docker

Entorno Docker: chenaotian/cve-2021-4034

Docker que construí yo mismo, que proporciona:

  1. pkexec compilado por mí mismo con símbolos de depuración.
  2. glibc con símbolos de depuración (parece que no sirve de mucho).
  3. gdb y sus complementos pwngdb y pwndbg (parece innecesario).
  4. El exploit en el entorno de depuración.

Todo está en el directorio /root/:

imagen-20220126183638493

  • El directorio exp contiene el exploit y run.sh; puede cambiar al usuario test con su test y luego ejecutarlo.
  • glibc-2.27 es el directorio del código fuente de glibc; probablemente no sea necesario, pero es útil para la depuración con gdb cuando se requiera.
  • polkit-0.105 es el paquete fuente de policykit.

Iniciar Docker:

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

Probar el exploit:

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

Principio de la vulnerabilidad

El producto donde ocurre la vulnerabilidad es el comando pkexec de polkit. pkexec es similar a sudo; ambos permiten ejecutar comandos como otro usuario (generalmente root). Se puede verificar el paquete al que pertenece pkexec con el comando dpkg:

dpkg -S /usr/bin/pkexec

imagen-20220126152839307

Luego se obtiene el paquete fuente (también está en mi Docker) y se compila una versión depurable para facilitar el análisis.

Punto de activación de la vulnerabilidad

El principio de activación es muy simple.

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

int
main (int argc, char *argv[])
{
    
  ··· ···
  ··· ···
      
  /* Esto significa: recorrer los parámetros de entrada del usuario y establecer valores según los diferentes parámetros ingresados.
   * Pero el problema es que el inicio del bucle es 1, sin considerar el caso en que el usuario no ingresa ningún parámetro.
   */
  for (n = 1; n < (guint) argc; n++) 
    {
      if (strcmp (argv[n], "--help") == 0)
        {
          opt_show_help = TRUE;
        }
      ··· ···
      else // si es un parámetro no reconocido, sale del bucle; esto significa que ese parámetro es el comando a ejecutar
        {
          break;
        }
    }

  ··· ···

  g_assert (argv[argc] == NULL);
  path = g_strdup (argv[n]); // obtiene la cadena específica del comando a ejecutar
  if (path == NULL)
    {
      ···
    }
  if (path[0] != '/')
    {
      /* g_find_program_in_path() no es susceptible a ataques a través del entorno */
      // Esta función busca la ruta absoluta del comando a ejecutar según la variable de entorno PATH
      s = g_find_program_in_path (path); 
      if (s == NULL)
        {
          ···
        }
      g_free (path);
      argv[n] = path = s;// reescribe la ruta absoluta obtenida en el parámetro de línea de comandos
    }
  ··· ···
  ··· ···

Según mi análisis en los comentarios del código:

  1. Primero, en la función main se establecen algunas variables según los argumentos de línea de comandos ingresados por el usuario, pero el bucle for comienza en 1, lo que significa que asume que al menos pasaremos un argumento (el comando que pkexec debe ejecutar).
  2. Si encuentra un argumento que no comienza con --, lo considera el comando a ejecutar con pkexec y sale del bucle para continuar con la lógica posterior.
  3. Llama a la función g_find_program_in_path para buscar la ruta absoluta del comando. Esta función busca la ruta absoluta del argumento (comando) según la variable de entorno PATH. Por ejemplo, si se pasa cat, devuelve /bin/cat.
  4. Reescribe la ruta absoluta devuelta en la posición de ese argumento de línea de comandos. (Se puede entender como convertir el comando a la ruta absoluta del archivo correspondiente).

Es bastante fácil de entender, pero el problema está en:

  1. Cuando se ejecuta un binario en Linux, los argumentos de línea de comandos argv[] y las variables de entorno environ[] se colocan en la parte inferior de la pila, y argv[] y environ[] están contiguos. El último elemento de argv[] es null.

    imagen-20220126162140802

  2. Si pkexec se inicia desde la línea de comandos sin ningún otro argumento, entonces argv[0] es "pkexec" y argv[1] es \x00, no hay problema. Pero si pkexec se inicia con la función execve sin ningún otro argumento, entonces argv[0] es \x00 y argv[1] apunta a la variable de entorno. ¡Cuando se lee argv[1], se desborda y lee environ[0]!

    Inicio directo desde línea de comandos de pkexec con argc = 1, argv[0] es la ruta de pkexec:

    imagen-20220126162616203

    Inicio de pkexec con execve, argc = 0:

    imagen-20220126162804529

¿Qué impacto tiene esto? Cuando se inicia con execve sin ningún otro argumento, la longitud de argv[] es 0, por lo que argv[1] es environ[0]. La lógica analizada anteriormente se convierte en: obtener el valor de la primera variable de entorno, buscar su ruta absoluta desde la variable PATH. Si la encuentra, la reescribe en la primera variable de entorno. Entonces la forma de explotación es la siguiente:

Explotación de la vulnerabilidad

Primero, hay que aclarar que pkexec es un archivo privilegiado (suid):

imagen-20220126161324831

¿Cómo aprovechar las variables de entorno en un archivo privilegiado para causar problemas? Primero, hay que conocer un pequeño detalle:

Un pequeño detalle

El enlazador dinámico de Linux ld-linux-x86-64.so.2 limpia las variables de entorno sensibles cuando se ejecuta un programa privilegiado:

Función _dl_non_dynamic_init: glibc-2.27/elf/dl-support.c : 307

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

  if (__libc_enable_secure) // en modo privilegiado
    {
      static const char unsecure_envvars[] =
	UNSECURE_ENVVARS
#ifdef EXTRA_UNSECURE_ENVVARS
	EXTRA_UNSECURE_ENVVARS
#endif
	;
      const char *cp = unsecure_envvars;

      // recorre y limpia (unset) todas las variables de entorno de la lista de peligrosas
      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 lista de variables de entorno peligrosas UNSECURE_ENVVARS se define así:

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

Descargar herramienta