Основна уязвимост в ядрото на Linux и отказ на услуга в systemd

Изследователи по сигурността от Qualys разкриха подробности за две уязвимости, засягащи ядрото на Linux и системния мениджър systemd. Уязвимост в ядрото (CVE-2021-33909) позволява на локален потребител да постигне изпълнение на код с root права чрез манипулиране на силно вложени директории.

Опасността от уязвимостта се утежнява от факта, че изследователите са успели да подготвят работещи експлойти, които работят на Ubuntu 20.04/20.10/21.04, Debian 11 и Fedora 34 в конфигурацията по подразбиране. Отбелязва се, че други дистрибуции не са тествани, но теоретично също са податливи на проблема и могат да бъдат атакувани. Обещава се пълният код на експлойтите да бъде публикуван, след като проблемът бъде елиминиран навсякъде, но засега е наличен само прототип с ограничена функционалност, което води до срив на системата. Проблемът съществува от юли 2014 г. и засяга версиите на ядрото, започващи от 3.16. Корекцията на уязвимостта беше координирана с общността и приета в ядрото на 19 юли. Основните дистрибуции вече са генерирали актуализации на своите пакети на ядрото (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch).

Уязвимостта е причинена от неуспешна проверка на резултата от преобразуване на size_t в int преди извършване на операции в кода seq_file, който създава файлове от поредица от записи. Неуспешната проверка може да доведе до записване извън границите на буфера при създаване, монтиране и изтриване на много вложена структура на директория (размер на пътя по-голям от 1 GB). В резултат на това атакуващият може да постигне 10-байтов низ "//deleted", записан с отместване от "-2 GB - 10 байта", сочещ към областта, непосредствено предшестваща разпределения буфер.

Подготвеният експлойт изисква 5 GB памет и 1 милион свободни inodes за работа. Експлойтът работи, като извиква mkdir(), за да създаде йерархия от около милион поддиректории, за да постигне размер на пътя на файла над 1 GB. Тази директория се монтира чрез bind-mount в отделно потребителско пространство от имена, след което се изпълнява функцията rmdir(), за да я премахне. Успоредно с това се създава нишка, която зарежда малка eBPF програма, която се блокира на етапа след проверка на eBPF псевдокода, но преди нейната JIT компилация.

В непривилегированото пространство на имената на userid се отваря файлът /proc/self/mountinfo и се чете дългото име на монтираната чрез свързване директория, което води до записването на низа "//deleted" в областта преди началото на буфера. Позицията за запис на реда е избрана така, че да презаписва инструкцията във вече тестваната, но все още некомпилирана eBPF програма.

След това, на програмно ниво eBPF, неконтролираното писане извън буфер се трансформира в контролирана способност за четене и запис в други структури на ядрото чрез манипулиране на структурите btf и map_push_elem. В резултат експлойтът определя местоположението на буфера modprobe_path[] в паметта на ядрото и презаписва пътя „/sbin/modprobe“ в него, което ви позволява да инициирате стартирането на всеки изпълним файл с root права в случай на извикване на request_module(), което се изпълнява например при създаване на netlink сокет.

Изследователите предоставят няколко решения, които са ефективни само за конкретен експлойт, но не елиминират самия проблем. Препоръчва се да зададете "/proc/sys/kernel/unprivileged_userns_clone" на 0, за да забраните монтирането на директории в отделно пространство от имена на потребителски идентификатори, и "/proc/sys/kernel/unprivileged_bpf_disabled" на 1, за да забраните зареждането на eBPF програми в ядрото.

Трябва да се отбележи, че докато анализират алтернативна атака, включваща използването на механизма FUSE вместо bind-mound за монтиране на голяма директория, изследователите се натъкват на друга уязвимост (CVE-2021-33910), засягаща системния мениджър systemd. Оказа се, че при опит за монтиране на директория с размер на пътя над 8 MB чрез FUSE, процесът на инициализация на контрола (PID1) изчерпва паметта на стека и се срива, което поставя системата в състояние на „паника“.

Проблемът е, че systemd проследява и анализира съдържанието на /proc/self/mountinfo и обработва всяка точка на монтиране във функцията unit_name_path_escape(), която изпълнява операция strdupa(), която поставя данните в стека, а не в динамично разпределената памет . Тъй като максималният размер на стека е ограничен чрез RLIMIT_STACK, обработката на твърде голям път до точката на монтиране води до срив на PID1 процеса и спиране на системата. За атака можете да използвате най-простия модул FUSE в комбинация с използване на силно вложена директория като точка на монтиране, чийто размер на пътя надвишава 8 MB.

Проблемът се появява от systemd 220 (април 2015 г.), вече е коригиран в основното хранилище на systemd и е коригиран в дистрибуции (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch). Трябва да се отбележи, че в systemd версия 248 експлойтът не работи поради грешка в кода на systemd, която причинява неуспешна обработка на /proc/self/mountinfo. Също така е интересно, че през 2018 г. възникна подобна ситуация и когато се опитваха да напишат експлойт за уязвимостта CVE-2018-14634 в ядрото на Linux, изследователите на Qualys се натъкнаха на три критични уязвимости в systemd.

Източник: opennet.ru

Добавяне на нов коментар