Bezpečnostní výzkumníci z firmy Qualys odhalili detaily dvou zranitelností zasahujících do jádra Linux a systémového správce systemd. Zranitelnost v jádře (CVE-2021-33909) umožňuje lokálnímu uživateli dosáhnout provedení kódu s právem root pomocí manipulací s adresáři s velkou hloubkou.
Nebezpečí zranitelnosti je umocněno tím, že výzkumníkům se podařilo připravit funkční exploit, který funguje na Ubuntu 20.04/20.10/21.04, Debian 11 a Fedora 34 ve výchozí konfiguraci. Je poznamenáno, že jiné distribuce nebyly testovány, ale teoreticky jsou také náchylné k problémům a mohou být napadeny. Kompletní kód exploitů má být zveřejněn po celoplošném odstranění problému, zatím je k dispozici pouze omezený prototyp, který způsobuje pád systému. Problém se projevuje od července 2014 a zasahuje vydání jádra počínaje verzí 3.16. Oprava zranitelnosti byla koordinována se komunitou a byla zařazena do jádra 19. července. Hlavní distribuce již připravily aktualizace balíčků s jádrem (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch).
Zranitelnost je způsobena absencí kontroly výsledku převodu typu size_t na int před prováděním operací ve funkci seq_file, která vytváří soubory ze sekvence záznamů. Nedostatek kontroly může vést k zápisu do oblasti mimo hranice vyrovnávací paměti při vytváření, montování a odstranění struktury adresářů s velmi vysokou úrovní vnoření (délka cesty přes 1 GB). V důsledku toho může útočník dosáhnout zápisu 10-bytového řetězce „//deleted“ s posunem „-2 GB - 10 bytů“, což ukazuje na oblast těsně před přidělenou vyrovnávací pamětí.
Připravený exploit vyžaduje k provozu 5 GB paměti a 1 milion volných inode. Fungování exploitů spočívá ve vytvoření prostřednictvím volání mkdir() hierarchie z přibližně milionu vnořených adresářů, aby se dosáhlo velikosti souborové cesty přesahující 1 GB. Tento adresář je namontován prostřednictvím bind-mount v odděleném prostoru jmen identifikátorů uživatelů (user namespace), po čemž je spuštěna funkce rmdir() pro jeho odstranění. Paralelně je vytvářen vlákno, které načítá malý program eBPF, který je blokován ve fázi po kontrole pseudokódu eBPF, ale před jeho JIT-kompilací.
V neprivilegovanom priestore mien identifikátorov používateľov sa otvorí súbor /proc/self/mountinfo a začne sa čítanie dlhého cestovného adresára, pripojeného pomocou bind-mount, čo vedie k zapísaniu reťazca „//deleted“ do oblasti pred začiatkom buffera. Pozícia na zápis reťazca sa vyberá tak, aby prepísala inštrukciu už skontrolovaného, ale ešte neskompilovaného programu eBPF.
Ďalej na úrovni programu eBPF nekontrolovaný zápis mimo buffera sa transformuje na manažovanú možnosť čítania a zápisu do iných štruktúr jadra cez manipuláciu so štruktúrami btf a map_push_elem. V dôsledku toho exploit určuje umiestnenie buffera modprobe_path[] v pamäti jadra a prepíše v ňom cestu „/sbin/modprobe“, čo umožní spustiť akýkoľvek vykonateľný súbor s právami root, pokiaľ sa vykoná volanie request_module(), ktoré sa vykonáva napríklad pri vytváraní socketu netlink.
Výskumníci uvádzajú niekoľko obchádzacích metód ochrany, ktoré sú efektívne len pre konkrétny exploit, ale nevyriešia samotný problém. Odporúča sa nastaviť parameter „/proc/sys/kernel/unprivileged_userns_clone“ na hodnotu 0 na zákaz montovania adresárov v samostatnom priestore mien identifikátorov používateľov a tiež „/proc/sys/kernel/unprivileged_bpf_disabled“ na 1 na zákaz načítania programov eBPF do jadra.
Zaujímavé je, že pri skúmaní alternatívneho variantu útoku, ktorý súvisí s použitím mechanizmu FUSE namiesto bind-mount na montovanie veľkého adresára, sa výskumníci stretli s ďalšou zraniteľnosťou (CVE-2021-33910), ktorá sa týka systémového správcu systemd. Ukázalo sa, že pri pokuse o montovanie cez FUSE adresára s dĺžkou cesty, ktorá presahuje 8 MB, nastáva v riadiacom procese inicializácie (PID1) vyčerpanie pamäte zásobníka a pád, ktorý vedie systém do stavu „panic“.
Problém spočíva v tom, že systemd sleduje a analyzuje obsah /proc/self/mountinfo a spracováva každú bod montovania vo funkcii unit_name_path_escape(), kde sa vykonáva operácia strdupa(), ktorá ukladá dáta na zásobník, a nie do dynamicky alokovanej pamäte. Keďže maximálna veľkosť zásobníka je obmedzená cez RLIMIT_STACK, spracovanie príliš dlhého cesty k bodu montovania vedie k pádu procesu PID1 a zastaveniu systému. Na útok možno využiť najjednoduchší modul FUSE v kombinácii s použitím ako bod montovania adresára s veľkým stupňom vnorenia, ktorého dĺžka cesty presahuje 8 MB.
Problém sa prejavuje od systemd 220 (apríl 2015), už bol odstránený v hlavnom repozitári systemd a opravený v distribúciách (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch). Zaujímavé je, že v vydaní systemd 248 exploity nefungujú kvôli chybám v kóde systemd, ktoré vedú k pádu pri spracovaní /proc/self/mountinfo. Taktiež je zaujímavé, že v roku 2018 došlo k podobnej situácii a pri pokuse o napísanie exploitov k zraniteľnosti CVE-2018-14634 v jadre Linuxu sa výskumníci z Qualys stretli s tromi kritickými zraniteľnosťami v systemd.
Zdroj: opennet.ru
