Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2021-3156-Heap-Based-Buffer-Overflow-in-Sudo-Baron-Samedit- | Kitploit
Strumenti/GitHubGitHub/sornphut/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit-
Escalation di PrivilegiAnalisi delle VulnerabilitàExploitPenetration TestingPaper e RicercaApprendimento e FormazioneBinary Exploitation
GitHubsornphut/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit-

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2021-3156-Heap-Based-Buffer-Overflow-in-Sudo-Baron-Samedit-

Vedi Repository
1 anno faNon ancora revisionato

Qualys Security Advisory

Baron Samedit: buffer overflow basato su heap in Sudo (CVE-2021-3156)

======================================================================== Indice

Sommario Analisi Sfruttamento Riconoscimenti Cronologia

======================================================================== Sommario

Abbiamo scoperto un buffer overflow basato su heap in Sudo (https://www.sudo.ws/). Questa vulnerabilità:

  • è sfruttabile da qualsiasi utente locale (utenti normali e utenti di sistema, sudoers e non sudoers), senza autenticazione (cioè l'attaccante non ha bisogno di conoscere la password dell'utente);

  • è stata introdotta nel luglio 2011 (commit 8255ed69) e interessa tutte le versioni legacy dalla 1.8.2 alla 1.8.31p2 e tutte le versioni stabili dalla 1.9.0 alla 1.9.5p1, nella loro configurazione predefinita.

Abbiamo sviluppato tre exploit diversi per questa vulnerabilità e ottenuto privilegi di root completi su Ubuntu 20.04 (Sudo 1.8.31), Debian 10 (Sudo 1.8.27) e Fedora 33 (Sudo 1.9.2). Probabilmente anche altri sistemi operativi e distribuzioni sono sfruttabili.

======================================================================== Analisi

Se Sudo viene eseguito per lanciare un comando in modalità "shell" (shell -c command):

  • tramite l'opzione -s, che imposta il flag MODE_SHELL di Sudo;

  • oppure tramite l'opzione -i, che imposta i flag MODE_SHELL e MODE_LOGIN_SHELL di Sudo;

allora, all'inizio della funzione main() di Sudo, parse_args() riscrive argv (righe 609-617), concatenando tutti gli argomenti della riga di comando (righe 587-595) e facendo l'escaping di tutti i metacaratteri con backslash (righe 590-591):


571 if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) { 572 char **av, *cmnd = NULL; 573 int ac = 1; ... 581 cmnd = dst = reallocarray(NULL, cmnd_size, 2); ... 587 for (av = argv; *av != NULL; av++) { 588 for (src = *av; src != '\0'; src++) { 589 / quote potential meta characters */ 590 if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '$') 591 *dst++ = '\'; 592 *dst++ = *src; 593 } 594 -c cmnd */ ... 603 av = reallocarray(NULL, ac + 1, sizeof(char *)); ... 609 av[0] = (char plugin may override shell */ 610 if (cmnd != NULL) { 611 av[1] = "-c"; 612 av[2] = cmnd; 613 } 614 av[ac] = NULL; 615 616 argv = av; 617 argc = ac; 618 }

Successivamente, in sudoers_policy_main(), set_cmnd() concatena gli argomenti della riga di comando in un buffer basato su heap "user_args" (righe 864-871) e rimuove l'escaping dei metacaratteri (righe 866-867), "per scopi di corrispondenza e registrazione sudoers":


819 if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { ... 852 for (size = 0, av = NewArgv + 1; *av; av++) 853 size += strlen(*av) + 1; 854 if (size == 0 || (user_args = malloc(size)) == NULL) { ... 857 } 858 if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) { ... 864 for (to = user_args, av = NewArgv + 1; (from = *av); av++) { 865 while (*from) { 866 if (from[0] == '\' && !isspace((unsigned char)from[1])) 867 from++; 868 *to++ = *from++; 869 } 870 *to++ = ' '; 871 } ... 884 } ... 886 }

Purtroppo, se un argomento della riga di comando termina con un singolo carattere backslash, allora:

  • alla riga 866, "from[0]" è il carattere backslash e "from[1]" è il terminatore nullo dell'argomento (cioè non un carattere spazio);

  • alla riga 867, "from" viene incrementato e punta al terminatore nullo;

  • alla riga 868, il terminatore nullo viene copiato nel buffer "user_args" e "from" viene incrementato di nuovo e punta al primo carattere dopo il terminatore nullo (cioè fuori dai limiti dell'argomento);

  • il ciclo "while" alle righe 865-869 legge e copia caratteri fuori dai limiti nel buffer "user_args".

In altre parole, set_cmnd() è vulnerabile a un buffer overflow basato su heap, perché i caratteri fuori dai limiti copiati nel buffer "user_args" non erano inclusi nella sua dimensione (calcolata alle righe 852-853).

In teoria, tuttavia, nessun argomento della riga di comando può terminare con un singolo carattere backslash: se MODE_SHELL o MODE_LOGIN_SHELL è impostato (riga 858, condizione necessaria per raggiungere il codice vulnerabile), allora MODE_SHELL è impostato (riga 571) e parse_args() ha già effettuato l'escaping di tutti i metacaratteri, inclusi i backslash (cioè ha fatto l'escaping di ogni singolo backslash con un secondo backslash).

In pratica, però, il codice vulnerabile in set_cmnd() e il codice di escaping in parse_args() sono circondati da condizioni leggermente diverse:


819 if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { ... 858 if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {

versus:


571 if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) {

La nostra domanda, quindi, è: possiamo impostare MODE_SHELL e MODE_EDIT o MODE_CHECK (per raggiungere il codice vulnerabile) ma non il MODE_RUN predefinito (per evitare il codice di escaping)?

La risposta, a quanto pare, è no: se impostiamo MODE_EDIT (opzione -e, riga 361) o MODE_CHECK (opzione -l, righe 423 e 519), allora parse_args() rimuove MODE_SHELL dai "valid_flags" (righe 363 e 424) ed esce con un errore se specifichiamo un flag non valido come MODE_SHELL (righe 532-533):


358 case 'e': ... 361 mode = MODE_EDIT; 362 sudo_settings[ARG_SUDOEDIT].value = "true"; 363 valid_flags = MODE_NONINTERACTIVE; 364 break; ... 416 case 'l': ... 423 mode = MODE_LIST; 424 valid_flags = MODE_NONINTERACTIVE|MODE_LONG_LIST; 425 break; ... 518 if (argc > 0 && mode == MODE_LIST) 519 mode = MODE_CHECK; ... 532 if ((flags & valid_flags) != flags) 533 usage(1);

Ma abbiamo trovato una scappatoia: se eseguiamo Sudo come "sudoedit" invece di "sudo", allora parse_args() imposta automaticamente MODE_EDIT (riga 270) ma non reimposta "valid_flags", e i "valid_flags" includono MODE_SHELL per impostazione predefinita (righe 127 e 249):


127 #define DEFAULT_VALID_FLAGS (MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME|MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_SHELL) ... 249 int valid_flags = DEFAULT_VALID_FLAGS; ... 267 proglen = strlen(progname); 268 if (proglen > 4 && strcmp(progname + proglen - 4, "edit") == 0) { 269 progname = "sudoedit"; 270 mode = MODE_EDIT; 271 sudo_settings[ARG_SUDOEDIT].value = "true"; 272 }

Di conseguenza, se eseguiamo "sudoedit -s", impostiamo sia MODE_EDIT che MODE_SHELL (ma non MODE_RUN), evitiamo il codice di escaping, raggiungiamo il codice vulnerabile e facciamo overflow del buffer basato su heap "user_args" tramite un argomento della riga di comando che termina con un singolo carattere backslash:


sudoedit -s '' perl -e 'print "A" x 65536' malloc(): corrupted top size Aborted (core dumped)

Dal punto di vista di un attaccante, questo buffer overflow è ideale:

  • controlliamo la dimensione del buffer "user_args" che mandiamo in overflow (la dimensione dei nostri argomenti della riga di comando concatenati, alle righe 852-854);

  • controlliamo in modo indipendente la dimensione e il contenuto dell'overflow stesso (il nostro ultimo argomento della riga di comando è opportunamente seguito dalle nostre prime variabili d'ambiente, che non sono incluse nel calcolo della dimensione alle righe 852-853);

  • possiamo persino scrivere byte nulli nel buffer che mandiamo in overflow (ogni argomento della riga di comando o variabile d'ambiente che termina con un singolo backslash scrive un byte nullo in "user_args", alle righe 866-868).

Ad esempio, su un Linux amd64, il seguente comando alloca un buffer "user_args" di 24 byte (un chunk heap di 32 byte) e sovrascrive il campo size del chunk successivo con "A=a\0B=b\0" (0x00623d4200613d41), il suo campo fd con "C=c\0D=d\0" (0x00643d4400633d43) e il suo campo bk con "E=e\0F=f\0" (0x00663d4600653d45):


env -i 'AA=a' 'B=b' 'C=c' 'D=d' 'E=e' 'F=f' sudoedit -s '1234567890123456789012'

--|--------+--------+--------+--------|--------+--------+--------+--------+-- | | |12345678|90123456|789012.A|A=a.B=b.|C=c.D=d.|E=e.F=f.| --|--------+--------+--------+--------|--------+--------+--------+--------+-- size <---- user_args buffer ----> size fd bk

======================================================================== Sfruttamento

Poiché Sudo chiama le funzioni di localizzazione all'inizio della sua funzione main():


154 setlocale(LC_ALL, ""); 155 bindtextdomain(PACKAGE_NAME, LOCALEDIR); 156 textdomain(PACKAGE_NAME);

e passa stringhe di traduzione (attraverso la funzione gettext() e la macro _()) a funzioni che accettano stringhe di formato, come:


301 sudo_printf(SUDO_CONV_ERROR_MSG, _("%s is not in the sudoers " 302 "file. This incident will be reported.\n"), user_name);

inizialmente abbiamo voluto riutilizzare l'affascinante tecnica di halfdog da https://www.halfdog.net/Security/2017/LibcRealpathBufferUnderflow/ e trasformare il buffer overflow basato su heap di Sudo in un exploit di tipo format-string. Più precisamente:

  • alla riga 154, in setlocale(), chiamiamo malloc() e free() su diverse variabili d'ambiente LC (LC_CTYPE, LC_MESSAGES, LC_TIME, ecc.), creando così piccoli buchi all'inizio dell'heap di Sudo (chunk fast o tcache liberi);

  • alla riga 155, bindtextdomain() alloca con malloc() una struct binding, che contiene un puntatore dirname al nome di una directory che contiene file di catalogo ".mo" e quindi stringhe di traduzione;

  • in set_cmnd(), allochiamo con malloc() il buffer "user_args" in uno dei buchi all'inizio dell'heap di Sudo e facciamo overflow di questo buffer, sovrascrivendo così il puntatore dirname della struct binding;

  • alla riga 301 (per esempio), gettext() (attraverso la macro _()) carica la nostra stringa di traduzione dal dirname sovrascritto -- in altre parole, controlliamo la stringa di formato passata a sudo_printf().

Per implementare questa tecnica iniziale, abbiamo scritto un brute-forcer rudimentale che esegue Sudo all'interno di gdb, fa overflow del buffer "user_args" e seleziona casualmente i seguenti parametri:

  • le variabili d'ambiente LC che passiamo a Sudo e la loro lunghezza (usiamo la locale "C.UTF-8" e aggiungiamo un "@modifier" casuale);

  • la dimensione del buffer "user_args" che mandiamo in overflow;

  • la dimensione dell'overflow stesso;

  • se passare o meno attraverso il codice di autenticazione di Sudo (opzione -A o -n) o no (opzione -u #realuid).

Purtroppo, questa tecnica iniziale è fallita; il nostro brute-forcer è riuscito a sovrascrivere il puntatore dirname della struct binding:


Program received signal SIGSEGV, Segmentation fault.

0x00007f6e0dde1ea9 in __dcigettext (domainname=domainname@entry=0x7f6e0d9cc020 "sudoers", msgid1=msgid1@entry=0x7f6e0d9cc014 "user NOT in sudoers", msgid2=msgid2@entry=0x0, plural=plural@entry=0, n=n@entry=0, category=5) at dcigettext.c:619

=> 0x7f6e0dde1ea9 <__dcigettext+1257>: cmpb $0x2f,(%rax)

rax 0x4141414141414141 4702111234474983745

ma LC_MESSAGES era sempre la locale predefinita "C" (non "C.UTF-8"), il che disabilita la traduzione delle stringhe in gettext() (cioè gettext() restituisce la stringa di formato originale, non la nostra).

Fortunatamente, però, il nostro brute-forcer ha prodotto decine di crash unici di Sudo e backtrace gdb; tra questi, tre hanno attirato la nostra attenzione e alla fine li abbiamo sfruttati tutti e tre.

======================================================================== 1/ sovrascrittura di struct sudo_hook_entry

Il primo crash che ha attirato la nostra attenzione è:


Program received signal SIGSEGV, Segmentation fault.

0x000056291a25d502 in process_hooks_getenv (name=name@entry=0x7f4a6d7dc046 "SYSTEMD_BYPASS_USERDB", value=value@entry=0x7ffc595cc240) at ../../src/hooks.c:108

=> 0x56291a25d502 <process_hooks_getenv+82>: callq *0x8(%rbx)

rbx 0x56291c1df2b0 94734565372592

0x56291c1df2b0: 0x4141414141414141 0x4141414141414141

Incredibilmente, la funzione process_hooks_getenv() di Sudo è andata in crash (alla riga 108) perché abbiamo sovrascritto direttamente un puntatore a funzione, getenv_fn (un membro di una struct sudo_hook_entry basata su heap):


99 int 100 process_hooks_getenv(const char *name, char **value) 101 { 102 struct sudo_hook_entry *hook; 103 char *val = NULL; ... 107 SLIST_FOREACH(hook, &sudo_hook_getenv_list, entries) { 108 rc = hook->u.getenv_fn(name, &val, hook->closure);

Per sfruttare questa sovrascrittura di struct sudo_hook_entry, notiamo che:

  • la chiamata a getenv_fn (alla riga 108) è compatibile con una chiamata a execve():

    . name ("SYSTEMD_BYPASS_USERDB") è compatibile con l'argomento pathname di execve();

    . &val (un puntatore a un puntatore NULL) è compatibile con argv di execve();

    . hook->closure (un puntatore NULL) è compatibile con envp di execve();

  • possiamo bypassare ASLR sovrascrivendo parzialmente il puntatore a funzione getenv_fn (che punta alla funzione sudoers_hook_getenv() nella libreria condivisa sudoers.so); e fortunatamente, l'inizio di sudoers.so contiene una chiamata a execve() (o execv()):


0000000000008a00 execv@plt: 8a00: f3 0f 1e fa endbr64 8a04: f2 ff 25 65 55 05 00 bnd jmpq *0x55565(%rip) # 5df70 <execv@GLIBC_2.2.5> 8a0b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)

  • possiamo leggere /dev/kmsg (dmesg) come utente non privilegiato su Ubuntu e quindi ottenere informazioni dettagliate sui nostri crash di Sudo.

Di conseguenza, adottiamo la seguente strategia:

  • Primo, facciamo brute-force dei parametri dell'exploit finché non sovrascriviamo getenv_fn con un indirizzo userland non valido (sopra 0x800000000000) -- finché non osserviamo un general protection fault nel punto della chiamata a getenv_fn:

sudoedit[15904] general protection fault ip:55e9b645b502 sp:7ffe53d6fa40 error:0 in sudo[55e9b644e000+1a000] ^^^

  • Poi, riutilizziamo questi parametri dell'exploit ma sovrascriviamo getenv_fn con un pattern regolare di indirizzi userland validi (sotto 0x800000000000) ma non mappati -- in questo esempio, getenv_fn è il 22° puntatore che sovrascriviamo (0x32 è '2', una parte del nostro pattern):

sudoedit[15906]: segfault at 323230303030 ip 0000323230303030 sp 00007ffeeabf2868 error 14 in sudo[55b036c16000+5000] ^^^^

  • Infine, sovrascriviamo parzialmente getenv_fn (sovrascriviamo i suoi due byte meno significativi con 0x8a00, l'offset di execv() in sudoers.so, e il suo terzo byte con 0x00, il terminatore nullo di user_args in set_cmnd()) finché non bypassiamo ASLR -- abbiamo una buona probabilità di sovrascrivere getenv_fn con l'indirizzo di execv() dopo 2^(3*8-12) = 2^12 = 4096 tentativi, eseguendo così il nostro binario, chiamato "SYSTEMD_BYPASS_USERDB", come root.

Abbiamo testato con successo questo primo exploit su Ubuntu 20.04.

======================================================================== 2/ sovrascrittura di struct service_user

Il secondo crash che ha attirato la nostra attenzione è:


Program received signal SIGSEGV, Segmentation fault.

0x00007f6bf9c294ee in nss_load_library (ni=ni@entry=0x55cf1a1dd040) at nsswitch.c:344

=> 0x7f6bf9c294ee <nss_load_library+46>: cmpq $0x0,0x8(%rbx)

rbx 0x41414141414141 18367622009667905

La funzione nss_load_library() della glibc è andata in crash (alla riga 344) perché abbiamo sovrascritto il puntatore "library", un membro di una struct service_user basata su heap:


327 static int 328 nss_load_library (service_user ni) 329 { 330 if (ni->library == NULL) 331 { ... 338 ni->library = nss_new_service (service_table ?: &default_table, 339 ni->name); ... 342 } 343 344 if (ni->library->lib_handle == NULL) 345 { 346 / Load the shared library. / 347 size_t shlen = (7 + strlen (ni->name) + 3 348 + strlen (__nss_shlib_revision) + 1); 349 int saved_errno = errno; 350 char shlib_name[shlen]; 351 352 / Construct shared object name. */ 353 __stpcpy (__stpcpy (__stpcpy (_"), 355 ni->name), 356 ".so"), 357 __nss_shlib_revision); 358 359 ni->library->lib_handle = __libc_dlopen (shlib_name);

Possiamo facilmente trasformare questa sovrascrittura di struct service_user in un'esecuzione arbitraria di codice:

  • sovrascriviamo ni->library con un puntatore NULL, per entrare nel blocco alle righe 330-342, evitare il crash alla riga 344 ed entrare nel blocco alle righe 344-359;

  • sovrascriviamo ni->name (un array di caratteri, inizialmente "systemd") con "X/X";

  • le righe 353-357 costruiscono il nome di una libreria condivisa "libnss_X/X.so.2" (invece di "libnss_systemd.so.2");

------------------------------------------------------------------------- alla riga 359, carichiamo la nostra libreria condivisa "libnss_X/X.so.2" dalla directory di lavoro corrente ed eseguiamo il nostro costruttore _init() come root.

Abbiamo testato con successo questo secondo exploit su Ubuntu 20.04, Debian 10, e Fedora 33.

======================================================================== 3/ sovrascrittura di def_timestampdir

Il nostro terzo exploit non deriva da uno dei crash di Sudo, ma da un' osservazione casuale: durante il nostro brute-force, Sudo ha creato decine di nuove directory nella nostra directory di lavoro corrente (AAAAAA, AAAAAAAAA, ecc.). Ognuna di queste directory appartiene a root e contiene solo un piccolo file, chiamato come il nostro utente: il file timestamp di Sudo -- evidentemente abbiamo sovrascritto def_timestampdir, il nome della directory dei timestamp di Sudo.

Se sovrascriviamo def_timestampdir con il nome di una directory che non esiste già, allora possiamo fare una race contro ts_mkdirs() di Sudo, creare un symlink a un file arbitrario e:

3a/ chown() questo file arbitrario a utente root e gruppo root;

3b/ oppure aprire (o creare) questo file arbitrario come root e scrivervi una struct timestamp_entry.

Non siamo riusciti a trasformare 3a/ in pieni privilegi di root (ad esempio, se eseguiamo chown() del nostro binario SUID a root, il kernel rimuove automaticamente il bit SUID del nostro binario). Se tu, caro lettore, trovi una soluzione a questo problema, pubblicala sulla mailing list pubblica oss-security!

Alla fine, siamo riusciti a trasformare 3b/ in pieni privilegi di root, ma inizialmente abbiamo affrontato due problemi:

  • timestamp_open() di Sudo elimina il nostro symlink arbitrario se il file a cui punta è più vecchio del tempo di boot. Siamo riusciti a risolvere questo primo problema creando un file timestamp molto vecchio (risalente all'epoca Unix), aspettando che timestamp_open() lo elimini e facendo una race contro timestamp_open() per creare il nostro symlink arbitrario finale.

  • Non controlliamo il contenuto della struct timestamp_entry che viene scritta nel file arbitrario. Per quanto ne sappiamo, controlliamo solo tre byte (un process ID o una struct timespec) e non siamo riusciti a trasformare questa scrittura di tre byte in pieni privilegi di root. Se tu, caro lettore, trovi una soluzione a questo problema, pubblicala sulla mailing list pubblica oss-security!

Tuttavia, siamo riusciti ad aggirare questo secondo problema abusando di un piccolo bug in timestamp_lock() di Sudo. Se vinciamo le due race contro ts_mkdirs() e timestamp_open(), e se il nostro symlink arbitrario punta a /etc/passwd, allora questo file viene aperto come root e:


65 struct timestamp_entry { 66 unsigned short version; /* version number / 67 unsigned short size; / entry size / 68 unsigned short type; / TS_GLOBAL, TS_TTY, TS_PPID */ .. 78 };

305 static ssize_t 306 ts_write(int fd, const char *fname, struct timestamp_entry *entry, off_t offset) 307 { ... 318 nwritten = pwrite(fd, entry, entry->size, offset); ... 350 }

619 bool 620 timestamp_lock(void *vcookie, struct passwd *pw) 621 { 622 struct ts_cookie *cookie = vcookie; 623 struct timestamp_entry entry; ... 644 nread = read(cookie->fd, &entry, sizeof(entry)); 645 if (nread == 0) { ... 652 } else if (entry.type != TS_LOCKEXCL) { ... 657 if (ts_write(cookie->fd, cookie->fname, &entry, 0) == -1)

  • alla riga 644, i primi 0x38 byte di /etc/passwd ("root❌0:0:...") vengono letti in una struct timestamp_entry basata sullo stack, entry;

  • alla riga 652, entry.type è 0x783a (":x"), non TS_LOCKEXCL;

  • alle righe 657 e 318, entry->size byte della entry basata sullo stack vengono scritti in /etc/passwd, ma entry->size è in realtà 0x746f ("ot"), non sizeof(struct timestamp_entry).

Di conseguenza, scriviamo l'intero contenuto dello stack di Sudo in /etc/passwd (inclusi i nostri argomenti da riga di comando e le nostre variabili d'ambiente): iniettiamo un utente arbitrario in /etc/passwd e otteniamo quindi pieni privilegi di root. Abbiamo testato con successo questo terzo exploit su Ubuntu 20.04.

Nota: questo piccolo bug in timestamp_lock() è stato corretto a gennaio 2020 dal commit 586b418a, ma la correzione non è stata backportata alle versioni legacy.

======================================================================== Ringraziamenti

Ringraziamo Todd C. Miller per la sua professionalità, la rapidità di risposta e l'attenzione meticolosa a ogni dettaglio del nostro rapporto. Ringraziamo anche i membri di distros@openwall.

======================================================================== Cronologia

2021-01-13: Advisory inviato a Todd.Miller@sudo.

2021-01-19: Advisory e patch inviati a distros@openwall.

2021-01-26: Data di rilascio coordinata (18:00 UTC).

Scarica lo strumento
dst++ = ' '; 595 } ... 600 ac += 2; /
)user_details.shell; /
stpcpy (shlib_name, 354 "libnss