Cercetătorii de securitate de la Qualys au dezvăluit detalii despre două vulnerabilități care afectează nucleul Linux și managerul de sistem systemd. Vulnerabilitatea din nucleu (CVE-2021-33909) permite unui utilizator local să execute cod cu drepturi de root prin manipularea directorilor cu o adâncire mare.
Pericolul acestei vulnerabilități este agravat de faptul că cercetătorii au reușit să dezvolte exploate funcționale care functionează pe Ubuntu 20.04/20.10/21.04, Debian 11 și Fedora 34 în configurația implicită. Este important de menționat că alte distribuții nu au fost testate, dar teoretic ele sunt, de asemenea, vulnerabile și pot fi atacate. Codul complet al exploatelor va fi publicat după remedierea generalizată a problemei, iar deocamdată este disponibil doar un prototip funcțional limitat, care cauzează prăbușirea sistemului. Problema este prezentă încă din iulie 2014 și afectează versiunile nucleului începând cu 3.16. Remedierea vulnerabilității a fost coordonată cu comunitatea și a fost acceptată în nucleu pe 19 iulie. Distribuțiile principale au implementat deja actualizări ale pachetelor cu nucleul (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch).
Vulnerabilitatea este cauzată de lipsa verificării rezultatului conversiei tipului size_t în int înainte de executarea operațiunilor în codul seq_file, care se ocupă cu crearea fișierelor dintr-o secvență de înregistrări. Lipsa verificării poate duce la scrierea în zona dincolo de limitele buffer-ului atunci când se creează, montează și șterge o structură de directoare cu un nivel de adâncime foarte mare (dimensiunea căii mai mare de 1 GB). Ca urmare, un atacator poate reuși să scrie un șir de 10 byte „//deleted” cu un offset „- 2 GB - 10 byte”, care indică zona imediat anterioară buffer-ului alocat.
Exploatul pregătit necesită pentru funcționare 5 GB de memorie și 1 milion de inode-uri libere. Funcționarea exploatului constă în crearea, prin apelul mkdir(), a unei ierarhii de aproximativ un milion de directoare înlănțuite pentru a atinge o dimensiune a căii fișierelor care depășește 1 GB. Acest director este montat prin bind-mount într-un spațiu de nume al identificatorilor de utilizatori, după care este apelată funcția rmdir() pentru a-i realiza ștergerea. În paralel, este creat un fir de execuție care încarcă un mic program eBPF, care este blocat în etapa ulterioară verificării pseudocodului eBPF, dar înainte de JIT-compilare.
În spațiul de nume neprivilegiat al identificatorilor de utilizator, se deschide fișierul /proc/self/mountinfo și începe citirea unui drum lung către un director, montat prin bind-mount, ceea ce duce la scrierea șirului „//deleted” în zona de dinaintea buffer-ului. Poziția de scriere a șirului este aleasă astfel încât să scrub instrucțiunea dintr-un program eBPF deja verificat, dar care nu a fost compilat încă.
Ulterior, la nivelul programului eBPF, scrierea necontrolată în afara buffer-ului se transformă într-o capacitate gestionată de citire și scriere în alte structuri de kernel prin manipularea structurilor btf și map_push_elem. În final, exploit-ul determină locația buffer-ului modprobe_path[] în memoria kernel-ului și îl rescrie cu calea „/sbin/modprobe”, permițând inițierea executării oricărui fișier executabil cu privilegii root în cazul în care se efectuează apelul request_module(), care are loc, de exemplu, la crearea unui socket netlink.
Cercetătorii prezintă mai multe metode de ocolire a protecției, care sunt eficiente doar pentru exploit-uri specifice, dar nu elimină problema în sine. Se recomandă setarea parametrului „/proc/sys/kernel/unprivileged_userns_clone” la valoarea 0 pentru a interzice montarea directorilor în spațiul de nume neprivilegiat al identificatorilor de utilizator, precum și „/proc/sys/kernel/unprivileged_bpf_disabled” la 1 pentru a interzice încărcarea programelor eBPF în kernel.
Este notabil că, în analiza unei variante alternative de atac, legată de utilizarea mecanismului FUSE în loc de bind-mount pentru montarea unui director mare, cercetătorii au descoperit o altă vulnerabilitate (CVE-2021-33910), care afectează managerul de sistem systemd. S-a constatat că, la încercarea de a monta un director prin FUSE cu o dimensiune a căii care depășește 8 MB, procesul de inițializare (PID1) se confruntă cu epuizarea memoriei stivei și crash-ul, ceea ce duce sistemul în starea de „panic”.
Problema este legată de faptul că systemd monitorizează și analizează conținutul /proc/self/mountinfo și procesează fiecare punct de montare în funcția unit_name_path_escape(), unde se execută operația strdupa(), care plasează datele pe stivă și nu în memorie alocată dinamic. Având în vedere că dimensiunea maximă a stivei este limitată prin RLIMIT_STACK, procesarea unui drum prea lung pentru punctul de montare duce la căderea procesului PID1 și oprirea sistemului. O atac poate folosi un modul FUSE simplu, în combinație cu montarea unui director cu un grad mare de adâncime, în care dimensiunea drumului depășește 8 MB.
Problema se manifestă începând cu systemd 220 (aprilie 2015), fiind deja remediată în depozitul principal systemd și corectată în distribuții (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch). Este de remarcat faptul că în versiunea systemd 248 exploatul nu funcționează din cauza unei erori în codul systemd, care duce la o eroare în procesarea /proc/self/mountinfo. De asemenea, este interesant că în 2018 a apărut o situație similară atunci când s-au făcut încercări de a scrie un exploat pentru vulnerabilitatea CVE-2018-14634 din kernelul Linux, cercetătorii de la Qualys întâlnind trei vulnerabilități critice în systemd.
Sursa: opennet.ro
