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

● CVE-2021-3156 · CVSS 9.8 · Crítica
Pesquisa · FlawOpen

CVE-2021-3156: Transbordamento de Heap no Sudo Baron Samedit

Análise técnica do Baron Samedit (CVE-2021-3156): como uma barra invertida no final de um argumento do sudo permitiu a qualquer usuário local obter privilégios de root.

💡 Explicação em Linguagem Simples (ELI5)

Imagine um funcionário que confere fichas e segue a regra: uma barra invertida significa 'trate a próxima letra como um texto comum'. Alguém entrega uma ficha que termina exatamente em uma barra invertida. O funcionário procura a próxima letra, mas a folha acabou. Em vez de parar, ele continua lendo a folha de baixo da pilha e sobrescrevendo as permissões de segurança.

Conceitos Centrais e Termos

binário setuid
Um executável que roda com privilégios do proprietário (root), e não do chamador.
transbordamento de heap
Gravação além do limite alocado na heap, corrompendo estruturas de memória adjacentes.
escalada local de privilégios
Obtenção de privilégios administrativos de root a partir de um usuário não privilegiado.

Análise de Causa Raiz

A causa raiz decorre de parâmetros de limite não validados em sistemas de código aberto, permitindo a dessincronização de estado e a evasão dos controles de segurança.

Fluxo de Ataque Passo 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-Fonte: Vulnerável vs. Seguro

✕ IMPLEMENTAÇÃO VULNERÁVEL
/* 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 */
✓ PATCH SEGURO E 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 Verificação de Segurança para Engenharia

References