Исследователи из Амстердамского свободного университета и Высшей школы Сант-Анны описали новый класс атак на спекулятивное исполнение - Branch Target Reuse (BTR, переиспользование цели перехода). Метод относится к семейству Spectre-v2 и обходит механизмы изоляции памяти на процессорах Intel, AMD и ARM. Уязвимость затрагивает движки JIT-компиляции (компиляции на лету), которые создают машинный код прямо во время работы программы. Практичность подтверждена двумя рабочими эксплойтами (вредоносным кодом, эксплуатирующим уязвимость): они читают хеш пароля root из памяти ядра Linux. Хеш попадает туда после того, как утилита su загрузит его из файла /etc/shadow. На процессоре Intel скорость утечки достигает 8 байт в секунду, так что хеш оказывается на руках за три-пять минут.
Детали уязвимости
Классические атаки Spectre-v2 опираются на предсказание косвенных переходов. Процессор угадывает адрес ветвления по записям в буфере адреса ветвления (BTB, Branch Target Buffer) и буфере истории переходов (BHB, Branch History Buffer). Если предсказание неверно, вычисления отменяются, но следы в кэше остаются. Именно их и считывает атакующий. Новизна BTR в том, что кэш предсказаний не синхронизируется с правками машинного кода. JIT-движок освобождает участок памяти и позже отдаёт его под новый код, а устаревшие записи в BTB продолжают жить. В итоге процессор спекулятивно переходит по старому адресу, и исполняется код, которого автор программы не писал. По сути, это первая практическая атака Spectre-v2, которая не требует подстановки чужой цели из другого участка кода - достаточно устаревшей записи предсказателя.
Эксплуатация строится в три шага. Сначала злоумышленник заставляет движок выделить тренировочный блок и вызывает переход на него, чтобы предсказатель запомнил адрес. Затем блок освобождается, а на его место приходит новый, большего размера. Наконец повторный переход уводит исполнение по устаревшему адресу, уже занятому чужим кодом. Там атакующий размещает гаджет (цепочку инструкций для утечки) и добивается попадания нужных данных в кэш. Обойти защиту от JIT-спрея, которая запрещает кодировать машинные команды в виде констант, удалось за счёт операндов в инструкциях перехода. Смещение потока исполнения на середину таких инструкций превращает безобидные на первый взгляд значения в рабочий код. Проще говоря, защита опиралась на предположение, что переход всегда приходит на начало команды, и это предположение удалось нарушить.
Основной целью стал классический BPF (cBPF, Classic Berkeley Packet Filter - механизм фильтрации, который ядро Linux применяет, в частности, в подсистеме seccomp). Seccomp ограничивает набор доступных процессу системных вызовов, и его используют контейнерные платформы вроде Docker. Фильтры cBPF доступны непривилегированному пользователю, поэтому атака не требует прав администратора. Эти фильтры выполняются перед каждым системным вызовом, так что попыток для утечки хватает. Демонстрация прошла на Ubuntu 24.04 со стандартным ядром 6.14.0-27-generic. Гаджет перебирает список запущенных процессов, находит процесс su, обходит таблицы страниц и по характерному префиксу определяет страницу с хешем пароля. Дополнительно исследователи показали, что включённое ослепление констант (constant blinding) от этой схемы не спасает: смещения переходов остаются под контролем атакующего.
Схема оказалась межплатформенной. Кроме ядра Linux авторы разобрали движок SpiderMonkey в Firefox и Oracle GraalVM. В SpiderMonkey условия для спекулятивного чтения памяти создаются через WebAssembly, однако рабочий эксплойт не собран, и компания Mozilla делает ставку на изоляцию сайтов по процессам. В GraalVM сборка мусора слишком быстро вытесняет записи предсказателя, поэтому утечки тоже не получилось. При этом исследователи не считают это полноценной защитой и полагают, что ограничение можно обойти. Oracle усилила GraalVM случайным размещением кэша JIT-кода. Среди проверенных процессоров самой уязвимой оказалась архитектура Intel, а на AMD атаку не демонстрировали из-за режима AutoIBRS, который отключает предсказание косвенных переходов.
Правку в ядро Linux добавили в начале июля. Она сбрасывает состояние предсказателя переходов процессорными инструкциями IBPB (барьер предсказания косвенных переходов) всякий раз, когда исполняемая область памяти в cBPF или eBPF используется повторно. Исправление вошло в выпуски 7.2-rc2, 7.1.4 и в стабильные ветки вплоть до 6.6.145. Ядро получило два идентификатора - CVE-2026-64507 и CVE-2026-64508. Об истории раскрытия известно, что производители оборудования и разработчики ядра получили уведомление в апреле 2025 года. Они попросили полный сквозной эксплойт как доказательство необходимости дорогих мер, и лишь после его появления развернули защиту. Администраторам стоит обновить ядро до выпусков с исправлением; на системах без обновления риск сохраняется, а ослепление констант само по себе проблему не закрывает.
История BTR показывает, как спекулятивные атаки перебираются из браузеров в ядро. Ещё недавно считалось, что атаки Spectre-v2 без подстановки чужой цели непрактичны. Работа амстердамской группы это опровергает: для надёжной утечки хватает устаревших записей предсказателя и аккуратной работы с памятью. Лёгкие меры вроде изоляции отдельных инструкций или ослепления констант помогают лишь частично. Надёжнее сбрасывать состояние предсказателя при освобождении кода, хотя такая мера сложнее в реализации и заметнее бьёт по производительности. Зато она не зависит от того, сумеет ли атакующий выровнять поток исполнения нужным образом.
Ссылки