Calif нашла в ядре OpenBSD 37-летнюю ошибку, ведущую к root

Calif нашла в ядре OpenBSD 37-летнюю ошибку, ведущую к root

Охранная компания Calif описала исследование локальной уязвимости в ядре OpenBSD, позволяющей обычному пользователю системы получить права root. Компания отмечает, что обычно публикует наступательные исследования, а защитную работу (помощь open-source проектам с исправлениями, подготовка патчей, улучшения в криптографии, внутренние инженерные проекты для клиентов) почти не освещает, этот материал показывает обе стороны сразу: в начале года Calif сообщила OpenBSD о нескольких уязвимостях, часто сразу с предложенными патчами.

Корень одной из проблем уходит примерно на 37 лет назад, к исходному коду BSD: счётчик количества подключений к разделяемому сегменту памяти был объявлен как знаковое 16-битное число (short) с максимумом 32 767. При определённой последовательности действий с разделяемой памятью этот счётчик можно довести до переполнения, и он становится отрицательным. Такое целочисленное переполнение может привести к состоянию use-after-free (обращению к уже освобождённой области памяти) через гонку потоков. В сочетании с отдельной, не связанной с ней ошибкой записи за границы буфера в ядре, это даёт цепочку, которая позволяет локально повысить привилегии до root. По словам авторов, цепочка сработала даже при включённых защитных механизмах OpenBSD, рандомизации ядра KARL и аппаратных SMAP/SMEP, и без использования отдельной уязвимости утечки информации. Технически выполнение кода в ядре было получено через примитив «запись-что-куда»: сама запись возникала из-за операции удаления из двусвязного списка (TAILQ_REMOVE), «что», это пользовательское отображение памяти, переведённое в режим, доступный супервизору (в обход SMAP/SMEP), а «куда», предсказуемый адрес указателя ядра. Для надёжности эксплойт опирается на то, что обработчики ioctl сетевых интерфейсов lo0 и enc0 в OpenBSD размещаются в памяти предсказуемо: аллокаторы памяти ядра (загрузочный и best-fit) не рандомизируют базовый адрес, хотя сама рандомизация ядра (KARL) рандомизирует адреса функций и данных.

Обе найденные ошибки устранены: переполнение счётчика и связанный use-after-free закрыты патчем errata 026, запись за границы буфера, errata 018. Calif также предлагает ряд дополнительных мер защиты на будущее: технику «безопасного отсоединения» (safe-unlinking), которая перед записью при удалении элемента списка проверяет инварианты двусвязного списка и вызывает abort() или panic() при их нарушении (такая защита уже есть в реализациях sys/queue.h у FreeBSD и NetBSD); рандомизацию адреса самоссылающегося отображения таблицы страниц памяти при каждой загрузке системы (если это не подойдёт, альтернативы вроде пометки этой структуры как доступной только для чтения); и рандомизацию выделений памяти в самом аллокаторе ядра, как базового адреса при загрузке, так и порядка выделений во время работы. Отдельно упомянуты существующий компиляторный санитайзер границ массивов (Calif сообщила об этом также FreeBSD как возможной защите и приватно передала проекту 21 найденную таким способом проблему) и готовящаяся функция компилятора Alloc Tokens, которая разделяет выделения памяти с указателями и без них, усложняя эксплуатацию переполнений и ошибок use-after-free. В заключении авторы отмечают, что в эпоху ИИ-ассистированного поиска уязвимостей устранение целых классов ошибок и усложнение условий для атаки становится только важнее.

Ключевые факты

  • Calif раскрыла цепочку локального повышения привилегий до root в ядре OpenBSD
  • Корень одной из ошибок, счётчик подключений к разделяемой памяти, объявленный знаковым 16-битным числом почти 37 лет назад в исходниках BSD; его переполнение ведёт к use-after-free
  • В сочетании с отдельной ошибкой записи за границы буфера в ядре это дало root даже при включённых KARL, SMAP и SMEP, без уязвимости утечки информации
  • Обе ошибки уже исправлены патчами OpenBSD errata 026 и errata 018
  • Calif предложила дополнительные меры защиты: safe-unlinking, рандомизацию адреса таблицы страниц памяти и аллокатора ядра, санитайзер границ массивов и будущую функцию компилятора Alloc Tokens

Почему это важно

Уязвимость показывает, что даже у OpenBSD, системы, которая десятилетиями считается образцом защищённого by design подхода (ASLR, W^X, привилегированное разделение, песочницы), в самом фундаменте кода, унаследованном от исходной BSD почти 40 лет назад, может скрываться критическая ошибка. Цепочка сработала несмотря на несколько включённых аппаратных и программных защит ядра, что подчёркивает: отдельные механизмы защиты не заменяют устранение целых классов ошибок.

Кому это важно

Разработчикам и администраторам OpenBSD и других BSD-систем, инженерам по безопасности ядра операционных систем, а также разработчикам компиляторов и защитных механизмов памяти, которым адресованы предложенные Calif меры (безопасное отсоединение списков, рандомизация аллокаторов, санитайзер границ массивов).

Как это применить

OpenBSD уже выпустила патчи errata 026 и 018, закрывающие обе описанные ошибки, администраторам актуальных систем стоит убедиться, что эти обновления установлены. Предложенные Calif дополнительные меры (safe-unlinking, рандомизация адреса таблицы страниц и аллокатора ядра, санитайзер границ массивов, будущая функция Alloc Tokens) в тексте представлены как рекомендации, а не как уже внедрённые изменения.

Можно ли доверять

Это первичный разбор от самой компании-исследователя (Calif), которая сообщила об уязвимостях OpenBSD и получила подтверждение в виде официальных патчей errata 026 и 018, факт исправления служит независимым подтверждением серьёзности находки. В тексте нет точных дат отправки отчёта и выхода патчей (указано лишь «начало года»), не названы конкретные авторы материала и не приведены идентификаторы CVE, а реакция разработчиков OpenBSD в материале не процитирована.

Риски и подводные камни

Сама компания предупреждает, что в условиях ускоренного ИИ-ассистированного поиска уязвимостей устранение отдельных ошибок становится менее надёжной стратегией защиты, важнее закрывать целые классы проблем и повышать сложность атаки в принципе. Предложенные меры (рандомизация аллокаторов, safe-unlinking и прочее) в материале описаны как рекомендации; принял ли их проект OpenBSD, в тексте не сообщается.

«Нам удалось получить локальный root в OpenBSD при включённых KARL, SMAP и SMEP, без использования уязвимости раскрытия информации»

— Calif, в разборе уязвимости