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-3156 — CVE-2021-3156 POC y Docker y informe de análisis | Kitploit
Herramientas/GitHubGitHub/chenaotian/cve-2021-3156
Escalada de PrivilegiosAnálisis de VulnerabilidadesAnálisis de CódigoExplotaciónIngeniería InversaDepuradoresFuzzingPruebas de PenetraciónAprendizaje y EducaciónExplotación de BinariosLabs y Práctica
11225hace 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
GitHub
chenaotian/cve-2021-3156

CVE-2021-3156

CVE-2021-3156 POC y Docker y informe de análisis

Ver Repositorio

CVE-2021-3156

[toc]

Resumen de la vulnerabilidad

ID de vulnerabilidad: CVE-2021-3156

Puntuación de vulnerabilidad:

Producto vulnerable: linux sudo

Versiones afectadas: 1.8.2-1.8.31sp12; 1.9.0-1.9.5sp1

Condiciones de explotación: local en linux; sudo con SUID y ejecutable

Efecto de explotación: escalada de privilegios local

Obtención del código fuente: https://www.sudo.ws/getting/source/

Configuración del entorno

Entorno Docker: chenaotian/cve-2021-3156

He creado un docker propio que proporciona:

  1. sudo compilado por mí mismo con soporte para depuración del código fuente
  2. glibc con símbolos de depuración
  3. gdb y los plugins de gdb pwngdb & pwndbg
  4. exp.c y el exp compilado exitosamente

Todo está en el directorio /root:

image-20220124223312224

  • El directorio exp es donde se encuentran el código del exp y el exp compilado, se puede ejecutar directamente en este docker
  • glibc-2.27 es el directorio del código fuente de la versión de libc en este entorno
  • sudo-1.8.21 es el directorio del código fuente de sudo en este entorno, que utilicé para compilarlo.

Prueba del exp:``` cd exp su test ./exp whoami

Consulte más adelante para contenido relacionado con depuración [algunos comandos de depuración](#一些调试命令)


## Principio de la vulnerabilidad

payload de activación de vulnerabilidad```shell
sudoedit -s '\' `python3 -c "print('A'*80)"`

Análisis del código fuente (sudo-1.8.21): Primero está la función main en sudo.c (sudo.c: 133):```c int main(int argc, char *argv[], char *envp[]) { int nargc, ok, status = 0; char **nargv, **env_add; char **user_info, **command_info, **argv_out, **user_env_out; struct sudo_settings *settings; struct plugin_container *plugin, *next; sigset_t mask; debug_decl_vars(main, SUDO_DEBUG_MAIN)

··· ···
··· ···

/* Parse command line arguments. */
//在这里处理输入参数,设置sudo_mode
sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add);

··· ···
··· ···
    
switch (sudo_mode & MODE_MASK) {
··· ···
··· ···
case MODE_EDIT:
case MODE_RUN:
    ok = policy_check(&policy_plugin, nargc, nargv, env_add,
	&command_info, &argv_out, &user_env_out);
    ··· ···
    ··· ···
}

··· ···
··· ···

}

- Primero, se llama a la función parse_args para procesar los parámetros que ingresamos, en realidad aquí solo ingresamos un `-s`, no hay nada que configurar, se establece sudo_mode en MODE_EDIT y MODE_SHELL.

- Luego, dependiendo de sudo_mode, MODE_EDIT llama a policy_check

A continuación, la función policy_check en sudo.c (sudo.c: 1136):```c
static int
policy_check(struct plugin_container *plugin, int argc, char * const argv[],
    char *env_add[], char **command_info[], char **argv_out[],
    char **user_env_out[])
{
    ··· ···
    ··· ···
    ret = plugin->u.policy->check_policy(argc, argv, env_add, command_info,
	argv_out, user_env_out);
    ···
}

Se llamó a la función de callback plugin->u.policy->check_policy ,se puede depurar para ver la función real de esta función:

image-20220123113326096

La función llamada es sudoers_policy_check en policy.c (policy.c: 760):```c static int sudoers_policy_check(int argc, char * const argv[], char *env_add[], char **command_infop[], char **argv_out[], char **user_env_out[]) { ··· ···

exec_args.argv = argv_out;
exec_args.envp = user_env_out;
exec_args.info = command_infop;

ret = sudoers_policy_main(argc, argv, 0, env_add, &exec_args);
··· ···
··· ···

}

Luego se invoca la función sudoers_policy_main en sudoers.c (sudoers.c: 224):```c
int
sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
    void *closure)
{
    ··· ···
    ··· ···

    /*
     * Make a local copy of argc/argv, with special handling
     * for pseudo-commands and the '-i' option.
     */
    if (argc == 0) {
	··· ···
    } else {
	/* Must leave an extra slot before NewArgv for bash's --login */
	NewArgc = argc;
	NewArgv = reallocarray(NULL, NewArgc + 2, sizeof(char *));
	··· ···
	}
	memcpy(++NewArgv, argv, argc * sizeof(char *));
	NewArgv[NewArgc] = NULL;
	··· ···
	}
    }
	··· ···
    cmnd_status = set_cmnd();
    ··· ···
    ··· ···
    ··· ···
}

Aquí se configuran algunas variables globales, NewArgc y NewArgv, como se muestra a continuación, que son los parámetros pasados.

image-20220123113819116

Después se entra en la función set_cmnd en sudoers.c (sudoers.c: 796):```c static int set_cmnd(void) { ··· ··· ··· ···

/* set user_args */
if (NewArgc > 1) {
    char *to, *from, **av;
    size_t size, n;

    /* Alloc and build up user_args. */
    //根据参数总长度计算size, 后续malloc 申请,没有问题
    for (size = 0, av = NewArgv + 1; *av; av++)
	size += strlen(*av) + 1;
    if (size == 0 || (user_args = malloc(size)) == NULL) {
	sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
	debug_return_int(-1);
    }
    if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {
	/*
	 * When running a command via a shell, the sudo front-end
	 * escapes potential meta chars.  We unescape non-spaces
	 * for sudoers matching and logging purposes.
	 */
     //将所有参数拷贝到一起放到堆中,逻辑是遇到'\'加非空格类型字符则只拷贝非空格字符
     //但这里\x00 并不算空格类型字符
     //他没有考虑参数如果只有一个'\'或以'\'结尾并且下两个字符后就是另一个字符串情况
	for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
	    while (*from) {
		if (from[0] == '\\' && !isspace((unsigned char)from[1]))
		    from++;
		*to++ = *from++;
	    }
	    *to++ = ' ';
	}
	*--to = '\0';
    } 
    ··· ···
}
}
··· ···
··· ···

}

El desbordamiento también ocurre aquí, según se puede ver en los comentarios del código, el desbordamiento del montón ocurre al copiar al montón. La intención original de este código no es difícil de entender: copiar todos los parámetros de NewArgv al montón, separados por espacios, y cuando se encuentra `\+<carácter no espaciado>`, solo copiar ese carácter.

**Pero no considera un caso: si un elemento de NewArgv termina con `\`, entonces es una estructura como `\+\x00`, y `\x00` no pertenece a la clase de caracteres espaciados (¡increíble!). Esto significa que, después de copiar `\x00` al montón, la variable `from` se incrementa (dos veces en un bucle) y se salta la oportunidad de que el bucle while termine con el marcador `\x00`, pensando que los parámetros no se han copiado por completo y continúa copiando hasta encontrar el siguiente `\x00`.**

En este escenario se puede ver que `\+\x00` va seguido inmediatamente del siguiente parámetro `A*80`, por lo que continúa copiando hasta el final de `A*80`. Pero no hay que olvidar que luego se procesará realmente el parámetro `A*80`, y se copiará de nuevo, por lo que aquí se copian dos veces `A*80`, pero el chunk se asignó según el tamaño de solo una cadena `A*80`, mucho menor que la longitud copiada.

image-20220123113907744

Luego se produce el desbordamiento, antes de copiar:

image-20220123114036691

Después de copiar:

image-20220123114137794

La ruta general de activación de la vulnerabilidad es (al depurar, basta con poner puntos de interrupción directamente según estas funciones):

- sudo.c : main
  - sudo.c : policy_check
    - policy.c : sudoerrs_policy_check
      - sudoers.c : sudoers_policy_main
        - sudoers.c : set_cmnd
          - sudoers.c : 859

## Principio de explotación de la vulnerabilidad
Descargar herramienta