
Relatório e pesquisa do CVE-2021-3156 (Baron Samedit)
Autor: IJ Baig
Data: 7 de julho de 2026
1.8.2 a 1.8.31p2, e versões estáveis 1.9.0 a 1.9.5p1.1.9.5p1Para analisar esta vulnerabilidade com segurança, a versão vulnerável do Sudo foi compilada dentro de um ambiente isolado e não produtivo.

O código fonte do Sudo 1.9.5p1 foi baixado e compilado localmente usando utilitários make padrão. Foi tomado cuidado para executar isso a partir de um diretório local para que não sobrescrevesse o binário sudo nativo e corrigido do sistema host.

Confirmação da Build: Após a compilação, o binário personalizado foi executado para verificar se a versão correta e vulnerável foi compilada.


plugins/sudoers/sudoers.cset_cmnd() (por volta da linha 864 na versão 1.9.5p1)
Imagine que você tem um ajudante cujo trabalho é remover caracteres de escape (barras invertidas) de uma lista de palavras antes de colocá-las em uma caixa de armazenamento recém-alocada (um buffer de heap). O ajudante assume cegamente que toda barra invertida é sempre seguida por um caractere válido, então, sempre que vê uma barra invertida, a pula e copia o próximo caractere.
No entanto, existe uma falha na forma como o programa processa argumentos ao executar sudoedit -s. Isso permite que um usuário introduza uma palavra que termina exatamente com uma única barra invertida (\), que é imediatamente seguida pelo marcador invisível de fim de palavra (um terminador nulo, \0).
Quando o código do ajudante atinge essa barra invertida final, ele a pula e olha para o próximo caractere — o terminador nulo. Em vez de parar, a lógica da instrução if força o ajudante a pular também o terminador nulo. O loop continua, copiando qualquer memória arbitrária fora dos limites que venha a seguir para a caixa de armazenamento. Essa cópia contínua além do comprimento pretendido da palavra causa um estouro do buffer designado, levando a um grave estouro de buffer baseado em heap.
Trecho do Código Vulnerável:
/* Desescapar caracteres, pulando barras invertidas */
for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
while (*from) {
// VULNERABILIDADE: Se from[0] for '\' e from[1] for '\0',
// o loop avalia como verdadeiro, incrementa 'from', pulando o terminador nulo.
if (from[0] == '\\' && !isspace((unsigned char)from[1]))
from++;
*to++ = *from++;
}
*to++ = ' ';
}
*--to = '\0';
Os desenvolvedores do Sudo corrigiram esse erro lógico na versão 1.9.5p2 adicionando uma verificação rigorosa de limites. O código agora garante explicitamente que o caractere após a barra invertida não seja o terminador nulo antes de tentar desescapá-lo.
Diff do Patch:
- if (from[0] == '\\' && !isspace((unsigned char)from[1]))
+ if (from[0] == '\\' && from[1] != '\0' && !isspace((unsigned char)from[1]))
Por que isso corrige a causa raiz:
A adição de from[1] != '\0' interrompe imediatamente a leitura fora dos limites. Agora, se o código encontrar uma barra invertida final no final da string (ou seja, from[1] é o terminador nulo), a instrução if será avaliada como falsa. O ponteiro não é incrementado prematuramente, o terminador nulo é processado corretamente como o fim da string, e o loop termina de forma segura sem estourar o heap.
Para esta reprodução, foi utilizado o exploit Python amplamente reconhecido desenvolvido pelo pesquisador de segurança Worawit (especificamente a variante exploit_nss.py).
Antes de executar o PoC, é fundamental entender sua mecânica. O script não apenas trava o programa; ele orquestra uma manipulação altamente precisa da memória para obter execução de código.
Aqui está o detalhamento passo a passo das operações do PoC:
.so). Este payload é projetado para executar /bin/sh como root.LC_ALL, LANG e TZ). Como o Sudo carrega variáveis de ambiente no heap na inicialização, o script calcula os tamanhos exatos necessários para organizar o heap em um layout previsível.sudoedit -s e passa um argumento de linha de comando terminando com uma única barra invertida. Isso aciona a vulnerabilidade de um a menos (off-by-one) discutida na Seção 2, causando uma escrita fora dos limites.service_user. Esta struct é usada pelo Name Service Switch (NSS) para consultar informações do sistema.service_user é corrompida para apontar para a biblioteca .so maliciosa compilada na Etapa 1. Quando o Sudo tenta consultar privilégios de usuário, ele carrega e executa cegamente a biblioteca do atacante, concedendo um shell root.Primeiro, um teste de crash básico foi realizado para provar que a vulnerabilidade existe sem armá-la.

Em seguida, o script completo exploit_nss.py do Worawit foi executado contra o binário vulnerável.

Para verificar a correção oficial, o mesmo acionador do PoC foi executado contra o binário corrigido do Sudo.
sudoedit -s '\' 2>&1 | grep -q "sudoedit:" && echo "Vulnerável" || echo "Não vulnerável"

O Sudo, um programa administrativo padrão usado em nossos servidores, contém uma falha crítica na forma como processa entradas de texto que contêm barras invertidas. Ao enviar cuidadosamente um comando malformado, um atacante com acesso básico de usuário pode enganar o sistema para escrever dados fora de sua área de memória designada. Esse erro permite que ele contorne completamente os controles de segurança e obtenha controle administrativo total e não autorizado sobre a máquina sem nunca precisar de uma senha.
Desafios: Um dos principais desafios foi a fragilidade da manipulação do heap. Payloads de exploração direcionados a versões específicas de SO muitas vezes falham em outras porque a biblioteca C padrão subjacente (glibc) gerencia blocos de memória de forma diferente. Armar com sucesso esta vulnerabilidade exigiu um entendimento exato do alinhamento de memória e dos layouts de variáveis de ambiente (Feng Shui do Heap) específicos para o ambiente alvo.