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

● CVE-2021-3156 · CVSS 9.8 · Critique
Recherche · FlawOpen

CVE-2021-3156 : Débordement de Tas dans Sudo Baron Samedit

Autopsie technique de Baron Samedit (CVE-2021-3156) : comment un caractère d'échappement mal géré dans sudo a offert les privilèges root à tout utilisateur local.

💡 Explication en Langage Simple (ELI5)

Imaginez un employé qui traite des formulaires avec la consigne : un antislash signifie 'traitez le caractère suivant littéralement'. Quelqu'un soumet une fiche se terminant par un antislash. L'employé continue d'écrire au-delà de la page et recopie par-dessus le document officiel suivant.

Concepts Clés et Termes

binaire setuid
Un programme s'exécutant avec les privilèges de son propriétaire (root) plutôt que ceux de l'utilisateur.
débordement de tas
Écriture au-delà des limites d'un bloc alloué sur le tas, corrompant la mémoire adjacente.
élévation locale de privilèges
Passage d'un accès utilisateur standard aux privilèges absolus de root.

Analyse de Cause Racine

La cause fondamentale provient de paramètres de limites non validés dans les systèmes open source, permettant une désynchronisation d'état et le contournement des contrôles de sécurité.

Déroulement de l'Attaque Étape par Étape

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.

Code Source : Vulnérable vs Sécurisé

✕ IMPLÉMENTATION VULNÉRABLE
/* 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 SÉCURISÉ ET ROBUSTE
/* 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';

Liste de Contrôle de Sécurité pour l'Ingénierie

References