flawopen.com/Teardowns/cve-2021-3156-sudo-baron-samedit

● CVE-2021-3156 · CVSS 9.8 · Crítica
Investigación · FlawOpen

CVE-2021-3156: Desbordamiento de Montículo en Sudo Baron Samedit

Análisis técnico de Baron Samedit (CVE-2021-3156): cómo un fallo en el desescapado de argumentos en sudo otorgó privilegios de root a cualquier usuario local.

💡 Explicación en Lenguaje Sencillo (ELI5)

Imagina un empleado de ventanilla que tiene una norma: una barra invertida indica que la letra siguiente debe copiarse tal cual. Alguien entrega un formulario que termina en una barra invertida sin nada detrás. El empleado no se detiene, se sale del papel y empieza a sobrescribir la mesa y los sellos de autorización oficiales.

Conceptos Clave y Términos

binario setuid
Un binario que se ejecuta con privilegios de su propietario (root) en lugar de los del usuario actual.
desbordamiento de montículo
Escritura fuera de los límites de una asignación en el heap, corrompiendo datos adyacentes.
escalada local de privilegios
Obtención de control total como root desde un usuario estándar sin privilegios.

Análisis de Causa Raíz

La causa raíz se debe a parámetros de límite no validados en sistemas de código abierto, lo que permite la desincronización de estado y la elusión de controles de seguridad.

Flujo de Ataque Paso a Paso

Step 1

Trailing Backslash Injection

Unprivileged user executes 'sudoedit -s \', bypassing normal argument escaping flags.

Step 2

Unterminated Buffer Traversal

The unescape pointer jumps past the null byte delimiter into uninitialized heap memory.

Step 3

Heap Corruption of Service Structures

The heap overflow overwrites the sudo_nss service structure in glibc.

Step 4

Root Privilege Escalation

Sudo loads an attacker-controlled shared library (/tmp/libnss_x.so.2) as root, granting instant root shell access.

Código Fuente: Vulnerable vs. Seguro

✕ IMPLEMENTACIÓN VULNERABLE
/* VULNERABLE: Unescape loop skips past string termination null byte */
for (to = user_args, from = NewArgv[0]; *from != '\0'; from++) {
    if (from[0] == '\\' && !isspace((unsigned char)from[1]))
        from++; /* BUG: If from[1] == '\0', loop skips past null terminator! */
    *to++ = *from;
}
*to = '\0'; /* Corrupts adjacent heap chunks with root auth structures */
✓ PARCHE SEGURO Y ROBUSTO
/* FIXED: Explicitly check that from[1] is neither space nor the null byte */
for (to = user_args, from = NewArgv[0]; *from != '\0'; from++) {
    if (from[0] == '\\' && from[1] != '\0' && !isspace((unsigned char)from[1]))
        from++;
    *to++ = *from;
}
*to = '\0';

Lista de Verificación de Seguridad para Ingeniería

References