Root-вразливість в ядрі 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 ГБ). У результаті атакуючий може досягти запису 10-байтового рядка "//deleted" зі зміщенням "- 2 ГБ - 10 байт", що вказує на область, що безпосередньо передує виділеному буферу.

Підготовлений експлоїт вимагає для роботи 5 ГБ пам'яті та 1 мільйон вільних inode. Робота експлоїту зводиться до створення через виклик mkdir() ієрархії близько мільйона вкладених каталогів для досягнення розміру файлового шляху, що перевищує 1 ГБ. Даний каталог монтується через bind-mount в окремому просторі імен ідентифікаторів користувачів (user namespace), після чого функція rmdir() запускається для його видалення. Паралельно створюється потік, що завантажує невелику програму eBPF, який блокується на стадії після перевірки псевдокоду eBPF, але до його JIT-компіляції.

У непривілейованому просторі імен ідентифікаторів користувачів відкривається файл /proc/self/mountinfo і починається читання довгого шляху каталогу, примонтованого за допомогою bind-mount, що призводить до запису рядка "//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. Виявилося, що при спробі монтування через FUSE каталогу з розміром шляху, що перевищує 8 МБ, в процесі ініціалізації (PID1), що управляє, настає вичерпання пам'яті стека і крах, який призводить систему в стан «panic».

Проблема пов'язана з тим, що systemd відстежує і розбирає вміст /proc/self/mountinfo, і обробляє кожну точку монтування функції unit_name_path_escape(), в якій виконується операція strdupa(), що розміщує дані в стеку, а не в пам'яті, що динамічно виділяється. Так як максимальний розмір стека обмежений через RLIMIT_STACK обробка занадто великого шляху до точки монтування призводить до краху PID1 процесу і зупинки роботи системи. Для атаки можна використовувати найпростіший модуль FUSE у поєднанні з використанням як точка монтування каталогу з великим рівнем вкладеності, розмір шляху в якому перевищує 8 МБ.

Проблема проявляється починаючи з 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

Додати коментар або відгук