37 лет под водой: уязвимость в ядре OpenBSD, уходящая корнями в оригинальный BSD
Компания Calif рассказала об эксплуатации уязвимости в ядре OpenBSD, историю которой можно проследить примерно на 37 лет назад — до оригинальных исходников BSD. Обычно фирма публикует наступательные исследования, но на этот раз речь идёт о работе, выполненной в связке с проектом: уязвимости были сообщены разработчикам, зачастую вместе с предлагаемыми патчами.
В чём ошибка
Корень проблемы — счётчик привязок разделяемой памяти, определённый как знаковое 16-битное целое (short). Многократное ветвление процесса с записями о привязках позволяло вытолкнуть счётчик за его максимум в 32 767 и «завернуть» его в отрицательное значение. Это целочисленное переполнение приводило к use-after-free через состояние гонки, а в сочетании с отдельной внеграничной записью в ядре давало локальное повышение привилегий до root. Проблемы устранены в errata 026 и 018.
Путь эксплуатации
Исследователям удалось получить локальный root без использования утечки информации. Схема такова: отобразить 127 сегментов разделяемой памяти SysV, снять их через munmap() и породить 259 процессов, доведя счётчик привязок до −32 643. Затем — подготовка кучи с опорой на метрики sysctl(KERN_MALLOCSTATS), выигрыш гонки с помощью IPC_RMID, выравнивание размещений IP-сокетов и установка IP_MULTICAST_TTL в нестандартное значение, чтобы выделить структуру ip_moptions.
Далее условная внеграничная запись −1 перезаписывает поля числа и максимума членств, после чего close() сокета запускает атомарные декременты, дважды меняющие самоссылающееся отображение PTE — из пользовательского в супервизорное. Так обходятся SMAP/SMEP и достигается исполнение кода в ядре через перезапись предсказуемого указателя. По сути это примитив «записать что куда»: «что» — пользовательская память, ставшая доступной супервизору, «куда» — предсказуемый адрес ядра.
Почему адреса предсказуемы
Механизм KARL перекомпоновывает ядро, рандомизируя адреса функций и данных, однако аллокаторы памяти остаются детерминированными. Ранние загрузочные выделения стабильно попадают в предсказуемые места на одном и том же оборудовании. Эксплойт надёжно нацеливается на обработчики ioctl для lo0 и enc0: один перезаписывается ради захвата потока управления, другой используется для восстановления указателя.
Что предлагают авторы
Calif перечисляет меры защиты: безопасное отсоединение элементов двусвязных списков (как в FreeBSD и NetBSD), рандомизация адреса самоссылающегося отображения PTE, недетерминированность аллокатора ядра. Отдельно отмечаются компиляторные средства — санитайзер границ массивов (его предложили FreeBSD вместе с 21 приватно сообщённой проблемой) и грядущие Alloc Tokens, изолирующие выделения с указателями. В эпоху поиска уязвимостей с помощью ИИ, подчёркивают авторы, устранение целых классов ошибок и повышение стоимости атаки становится лишь важнее.
Источник: Hacker News
Комментарии
Войдите, чтобы комментировать.