Безопасность в Linux — бесконечная игра в кошки-мышки между разработчиками и хакерами. Совсем недавно Ubuntu предпринял серьезные шаги для защиты от привилегированных атак, введя строгие ограничения на создание непривилегированных пространств имен (user namespaces) через механизм AppArmor. Казалось бы, защита идеальна. Но как обычно, реальность оказалась сложнее.
🛡 Что такое защита Ubuntu и зачем она нужна?
В апреле 2024 года разработчики Ubuntu приняли решение усилить безопасность системы, существенно ограничив возможность обычных (непривилегированных) пользователей создавать собственные пространства имен. Причина была веской: злоумышленники активно использовали эту возможность, чтобы получить привилегированный доступ к системе через уязвимые подсистемы, такие как сетевой стек или подсистема планирования.
Для этого был выбран подход на основе AppArmor — популярного механизма Mandatory Access Control (MAC), который позволяет устанавливать точные правила поведения для приложений и процессов в Linux.
Фактически новая система Ubuntu делала следующее:
- 📌 Все процессы, которые раньше могли свободно создавать непривилегированные пространства имен, теперь автоматически переводятся в особый профиль AppArmor — unprivileged_userns.
- ⛔ Этот профиль блокирует создание таких пространств имен, ограничивая доступ к критическим возможностям, например, CAP_SYS_ADMIN.
Выглядело это примерно так в логах системы:
[302291.395747] apparmor="DENIED" operation="capable" profile="unprivileged_userns" capability=21 capname="sys_admin"
🧐 Как обойти защиту?
Как это часто бывает в мире кибербезопасности, запреты создаются, чтобы их обходили. Исследователь под псевдонимом u1f383 в своем блоге подробно описал, как сумел обойти это ограничение, проведя тщательный анализ кода ядра Ubuntu.
Проблема оказалась в следующем:
- ⚙️ Ubuntu использует AppArmor для переключения процессов из неограниченного профиля (unconfined) в профиль с ограничениями (unprivileged_userns) при попытке создания пространства имен.
- 🔍 Однако процесс может самостоятельно переключить свой AppArmor-профиль через запись в файл /proc/self/attr/exec или /proc/self/attr/current.
- 🧩 Исследователь заметил, что если процесс самостоятельно переключается в любой другой профиль AppArmor, находящийся в статусе unconfined (например, профиль для приложения opam), то механизм безопасности обойти довольно просто.
Фактически, достаточно было выполнить такую команду:
echo "exec opam" > /proc/self/attr/exec
— и система позволяет спокойно создать непривилегированное пространство имен, несмотря на введенные ограничения.
⚡️ Технические детали реализации обхода
Всё дело в функции ядра aa_profile_ns_perm(), которая выполняла проверку текущего профиля. Если процесс использует стандартный профиль (unconfined), то ему автоматически назначался жесткий профиль unprivileged_userns, блокирующий создание пространств имен. Но если процесс уже был в другом, хотя и тоже неограниченном профиле, проверка проходила успешно, и ядро не применяло дополнительный ограничивающий профиль.
Это — классическая проблема дизайна безопасности: механизмы защиты полагались на предположение, что процесс находится в дефолтном состоянии. Возможность смены профиля без строгих проверок фактически оставила дыру в безопасности.
Исследователь предоставил два метода обхода в виде примеров на языке С:
- 📍 С помощью команды exec opam в /proc/self/attr/exec
- 📍 С помощью команды changeprofile opam в /proc/self/attr/current
Пример кода для переключения профиля и создания непривилегированного пространства имен выглядит так:
int fd = open("/proc/self/attr/exec", O_RDWR);
write(fd, "exec opam", strlen("exec opam"));
close(fd);
// Запуск команды unshare теперь возможен
execl("/usr/bin/unshare", "unshare", "-r", "-n", "-m", "/bin/bash", NULL);
🚨 Реакция Ubuntu и рекомендации по безопасности
Ubuntu оперативно отреагировал на эту уязвимость, подтвердив проблему и выпустив исправления в версии 25.04 и выше. Для пользователей более старых версий рекомендуется включить опцию ядра:
echo 1 > /proc/sys/kernel/apparmor_restrict_unprivileged_unconfined
Это предотвращает возможность переключения процессов на другие неограниченные профили и исключает описанный выше сценарий атаки.
🎭 Личное мнение автора статьи
Этот случай — яркий пример того, как даже самые сложные и продуманные механизмы безопасности могут иметь неожиданно простые и при этом критичные недостатки. Проблема возникла не столько из-за ошибки в реализации конкретной функции, сколько из-за базовых предположений, сделанных при проектировании защиты.
Интересно, что обнаружение уязвимости произошло буквально через несколько часов после начала анализа. И хотя сама находка стала не актуальной для конкурса Pwn2Own из-за изменения правил, она всё равно представляет собой ценнейший вклад в безопасность Linux и демонстрирует, насколько важно постоянно проверять и переосмысливать стратегии защиты.
В целом, история также показывает высокий уровень работы команды безопасности Ubuntu, которая быстро среагировала на уязвимость и предложила практические шаги по ее устранению.
🌐 Полезные ссылки и дополнительные материалы:
Этот случай ещё раз напоминает нам, что в мире информационной безопасности невозможно создать идеальную защиту — но всегда можно приблизиться к ней, если постоянно быть начеку. 🔐✨