Как стать автором
Обновить

Закрытие уязвимости Spectre в режиме безопасных вычислений на Эльбрусе

Уровень сложностиСредний
Время на прочтение9 мин
Количество просмотров2.3K
Всего голосов 13: ↑12 и ↓1+17
Комментарии16

Комментарии 16

Спасибо, познавательно! Нигде ранее не натыкался на информацию по узвимости Spectre именно через систему предсказаний(правда не особо-то и искал). Думал что эта уязвимость как-то связана с DMA, а тут вот оно как!

Проникновение Spectre в оперативную память через обучение предсказателя ветвлений (картинка)

Из диаграммы складывается такое впечатление, что в программу внедряется какой-то исполняемый код с шпионом, который и выполняется в пространстве этого процесса. Но Spectre всё-таки действует только в рамках своего процесса и никак не влияет на другие.

В целом, диаграмма ну очень непонятная. По идее, «Задача X» это и есть ваш процесс в котором вы манипулируете предсказателем ветвлений, но кто такой тогда красный Spectre справа?

Пробравшись, например, в серверы банков, Spectre может достать из оперативной памяти

Если вы банк и на ваших серверах исполняется произвольный бинарник, то кажется что-то пошло очень сильно не так и исправляется это совсем не борьбой со спекулятивными вычислениями.

Если же этот бинарник вы сами туда положили, то скорее стоит переработать методы защиты от Supply Chain-атак. Пожалуй, Spectre тут это не самая большая из ваших проблем.

Если же у вас всё хорошо с защитой цепочки поставок, но Spectre всё равно оказался в ваших бинарниках, то это может означать лишь то, что вы сами его реализовали и сами его собрали. Тогда действительно компиляция в режиме защищенных вычислений вам поможет, да.

Короче, в случае dedicated серверов за физически охраняемой решеткой и тотальным код-ревью, Spectre практически никак не играет роли. Этот класс узязвимостей опасен в основном на shared-платформах, где выполняется множество разных процессов, и не всем из них можно доверять. Например, компьютер пользователя.

У процессоров Эльбрус уязвимости Spectre нет на аппаратном уровне, но она проявляется на уровне компилятора

Но ведь буквально в начале описывается, что это аппартаная уязвимость, да и на протяжении всего текста аналогично: «это глубинная аппаратная уязвимость». Что значит «проявляется на уровне компилятора»?

Без оптимизации компилятора уязвимость не проявляется, потому что компилятор не будет генерировать спекулятивное чтение из памяти.

Я бы скорее ожидал ровно противоположного — с включенными оптимизациями компилятор не станет генерировать код, который заведомо не исполняется. А без оптимизаций он сгенерирует ровно то что и было написано — включая любые чтения из памяти.

Проверяли ли вы, что без оптимизаций уязвимость проверяется на заведомо уязвимых процессорах? Подозреваю, что здесь неправильно поставлен эксперимент и с выключенными оптимизациями уязвимость вообще никогда не воспроизводится вашим кодом (например, из-за проблем с достоверным замером времени исполнения инструкций).

Наиболее важные особенности этого режима в том, что он контролирует обращения за границами объектов, использование неинициализированных переменных и создание новых указателей и конверсию указателей.

Это реализовано на уровне компилятора или на аппаратном уровне? Если первое, то можно ли переписать весь ваш эксплоит на ассемблер и обойти все проверки? Всё-таки вряд ли вы будете контроллировать компиляцию зловредного кода =)

Если второе, то почему вы переключаете флаги компилятора? Кажется для демонстрации влияния защиты нужно переключать только защиту, и ничего больше. Иначе эксперимент какой-то некорректный выходит.

И программные заплатки, увы, не панацея, потому что не только не дают полной защиты, но и снижают производительность системы.

Я всё-таки буду предполагать что ваш режим защищенных вычислений всё-таки работает на уровне компилятора. Тогда чем же он не «программная заплатка»?

Наиболее важные особенности этого режима в том, что он контролирует обращения за границами объектов, использование неинициализированных переменных и создание новых указателей и конверсию указателей.

…и разве всё это не снижает производительность системы?

можно закрыть только переходом на другую архитектуру процессоров и отказом от спекулятивных вычислений

Но как же тогда в процессорах Apple Silicon (который M1, M2, M3) всё-таки Spectre пропатчили? Там же старый-добрый ARM в качестве архитектуры и спекулятивные вычисления всё также присутствуют. Аналогично с новыми поколениями Intel, AMD.

Intel, AMD, ARM, Microsoft, Linux и даже Mac выпустили патчи, которые отчасти закрывают уязвимость Spectre.

Нетехнический наброс, но корректнее было бы вместо Mac написать Apple, всё-таки Mac это лишь линейка продуктов, как, скажем «Intel Core».

Мда, статья важная, но написана так, что вообще не приближает к пониманию как работает уязвимость Spectre, тем более на Эльбрусе.

У процессоров Эльбрус уязвимости Spectre нет на аппаратном уровне, но она проявляется на уровне компилятора.

Во-во, и понимай как хочешь. Чтение последующего текста говорит о том, что Spectre в Эльбрусах есть на аппаратном уровне, и проявляется она на уровнях оптимизации -O2 и -O3.

Макрос black_box используется для предотвращения оптимизации компилятором значения переменной.

О мой мозг. "Предотвращения оптимизации компилятором значения переменной" - что бы это значило? Почему бы не написать, что это стандартный хак, гарантирующий, что значение переменной, заданной в параметре макроса, будет обрабатываться остальным кодом в явном виде? Все переменные в коде, прошедшие через данный макрос, будут гарантированно существовать в результирующем машинном коде - никакая оптимизация не предвычислит значение на этапе компиляции, не уберет из кода как неиспользуемое, не развернет цикл если переменная управляет циклом.

Прочтя всю статью я так и не понял, что же происходит в процессоре, когда спекулятивно выполняются команды. И каким образом происходит считывание секретной строки. Наличие исходников не помогает, например там появляется такая сущность как кеш, но не поясняется что это такое - то ли это просто массив для хранения временных значений, то ли это аппаратный кеш процессора, толи еще что-то - объяснений нет. Автор смог выдать только:

происходит попытка считать байты из секретной строки, используя ранее определенные функции get_byte(), find()

И что? Автор сам-то понимает, что происходит в этих функциях? А почему он об этом не пишет?

Это достигается за счет измерения времени доступа к различным индексам в области памяти map, используя разницу во времени, чтобы определить, к какому байту был получен доступ во время спекулятивного выполнения.

Что скрывается за словами "к какому байту"? К какому байту по счету? Или к какому байту в смысле к какому значению байта? Как из времени получается значение, и почему это работает? Ведь это самое важное.

В общем, люди разучились внятно объяснять. И постоянно нужно клещами вытягивать: то ли автор все знает о чем говорит, но не может объяснить, то ли автор только делает вид что понимает о чем говорит, потому и объяснения у него бессмысленные. Есть еще третий вариант: автор ленив настолько, что не хочет стараться формулировать мысли, а свою лень скрывает за фразами типа "кто разбирается - тот поймет". Интересно, увижу ли я когда-нибудь автора, который и разбирается и внятно объяснять умеет? Или это фантастика?

использование флагов меньшего уровня оптимизации (при уровнях оптимизации -О0 и -О1 Spectre не проявляется, при -О2 и выше - появляется);

Да там вроде есть специальный флаг отключающий спекулятивность, отказываться от оптимизаций совсем не вариант

-fno-control-spec Отключить механизм спекулятивности по управлению и по
данным на фазе if_conv

Эта опция, насколько я понимаю отключает и спекулятивные загрузки и спекулятивные операции вроде деления на ноль.

-fcontrol-spec Запретить использование спекулятивных обращений в память
-fno-dam Отключить DAM - аппаратный механизм разрешения конфликтов
по чтению-записи

А вот эти две опции отключают конкретно механизм спекулятивного обращения в память. DAM это тоже какой то буфер хранящий адреса, нужен он только при спекулятивном обращении в память, лучше тоже отключать вместе с ним.

Пожалуйста, исправьте таблицы.

Из объяснения в начале статьи невозможно понять, как работает Spectre. Например в Википедии понятное объяснение. У вас что-то другое и нелогичное.
У статьи 4 автора. Наверно кто-то один написал чушь, остальные не читали.

Как работает spectre:

  • пишешь код обращения к защищенной памяти, который никогда не будет выполняться

  • обманываешь предсказатель ветвлений чтобы он выполнил эту ветку кода (для этого нужно чтоб часть данных отсутствовала в L1 и включился предсказатель)

  • извлекаешь 1 бит из защищенной памяти и в зависимости от значения дергаешь заранее известный адрес

  • когда код исполняется проверяешь есть ли адрес в кэше (замером времени доступа например), так извлекается 1 бит

В эльбрусе нет предсказателя ветвлений, есть условное исполнение и подготовка ветвлений которые грузятся в конвеер, но реально не выполняются. В будущих процессорах предсказатель будет, интересно будет посмотреть работает ли в нем описываемая вами атака связанная с неверным предсказанием и возможным спекулятивным исполнением кода в нем. Если это будет работать это будет первая аппаратная уязвимость.

Текущая же демонстрирует скорей уязвимость софта (компилятора). А раз так то какие то ситуации компилятор мог бы и отлавливать.

Я про х64, эльбрус еще не изучал. Если там уязвимость в бинарнике, то ее и антивирусом можно найти.

А вообще spectre не так уж страшен, надо чтобы какой-то код долго исполнялся и перебирал биты в памяти, так как точно не знает где что-то расположено. Нужно как-то проанализировать всю извлеченную память. На арендованых серверах тоже не вариант его использовать, так как не может выйти за пределы VM.

А причем здесь вообще компилятор, если вредоносный код может быть собран хакером с нужным ему компилятором и флагами. Я вот думаю или вы чего то не понимаете или я) Пока мне кажется что таки вы...

еще раз как это работает - в систему каким то образом попадает и запускается вредоносный код, он исполняется под обычным пользовательским процессом, у которого нет доступа к участкам памяти других процессов. Этот код собран хакером дома, с нужными опциями, потому спекулятивное исполнение там точно будет работать, если процессор не находится в режиме защищенных вычислений. Так где здесь уязвимость компилятора? Вообще не важно на каком компиляторе и как собрана вся остальная система - главное чтоб хакерский кусок кода был собран правильно, а на это вы влиять никак не можете.

Компилятор при том, что именно он достает лоад из под проверки, нарушает порядок его исполнения и все вот это, именно он создает уязвимую ситуацию. В интеле же компилятор выдает правильный порядок, который уже нарушает само железо своим спекулятивным исполнением. В первом случае эльбрус не может ничего сделать, он понятия не имеет о первоначальной последовательности и просто исполняет то что дают, во втором компилятор никак не может запретить процессору менять порядок.

Поэтому и нельзя это считать полноценной аппаратной уязвимостью, максимум программно-аппаратной, и то в процессоре предусмотрены механизмы защиты, но именно софт их по разным причинам не использует.

Что касается васи хакера, то он конечно может много чего неприятного собрать подсунуть, например OpenSSL старой версии, но если компилятор начнет выявлять и закрывать/обходить такие грабли, то что вася-хакер с этим поделает? Не ну конечно может старым "дырявым" собирать тоже, да.

Я согласен с @krote. Компилятор не может считаться источником уязвимости, поскольку хакер может написать свой вредоносный код на Ассемблере, или даже создать свой собственный компилятор. Вы пишете, что компилятор «достает лоад из под проверки». Именно эта возможность является уязвимостью. Это аппаратная особенность.

>Компилятор при том, что именно он достает лоад из под проверки, нарушает порядок его исполнения и все вот это, именно он создает уязвимую ситуацию

Это если что про Spectre V2, здесь перекомпиляция действительно помогает, но не против Spectre V1.

Я уже разобрался, что автор пишет про два разных Spectre - V1 и V2, притом в первой половине статьи описывает принцип работы V2, хотя и мутно и с ошибками. Там действительно можно перекомпилировать защищаемый код, использующий косвенные переходы (патч сбивает тренировку предсказателя переходов), и код становится несколько медленней из за такого патча (retpoline). Именно у Эльбруса нет этого, потому к нему не применим Spectre V2.

Но предоставленный код это Spectre V1 и там уже пересборка защищаемого кода никак не способна помочь, а то что атака не работоспособна с отдельными опциями компиляции так это естественно - не надо собирать вредоносный код с такими опциями и все будет работать)

Автор вероятно подумал что V1 и V2 это одно и то же и не стал вообще упоминать об этом, но нет - это существенная деталь и принципиально разные атаки, хотя обе используют спекулятивное исполнение кода.

Ну и сам предоставленный код это просто демонстрация концепта, а не рабочий продакшн-код, он не считывает инфу у чужого процесса, из за чего многие в принципе стали сомневаться в работоспособности этой уязвимости на Эльбрусе. Но из того что сами производители Эльбруса позиционируют защищенный режим как защиту в том числе от Spectre (V1) - я полагаю что это достаточно подтверждение того что процессор имеет эту принципиальную уязвимость.

Ваше объяснение более сжато, конкретно и понятно. А автор статьи такое ощущение что вообще не представляет как работает то что он описывает. Как будто это какая то компиляция найденных им чужих текстов, из за чего у него встречаются такие обороты как "чтобы пробраться в код, в затем в оперативную память"
И более того завершает это все абсолютно неверным выводом:

У процессоров Эльбрус уязвимости Spectre нет на аппаратном уровне, но она проявляется на уровне компилятора.

Для использования Spectre нужна определенная последовательность команд, которая может убиться компилятором при ряде оптимизаций. Но в этом нет смысла так как хакер конечно же об этом знает и не будет использовать флаги компиляции которые не дадут ему использовать Sprectre. Так что как раз на аппаратном уровне уязвимость конечно же ВЫЯВЛЕНА, она не выявлена в режиме безопасных вычислений, где процессор тратит дополнительные ресурсы на проверку прав доступа выполняя код в спекулятивном режиме. Упоминание о компиляторе тут вообще не имеет смысла, так как компилировать свой вредоносный код-нагрузку будет хакер, на том на чем ему удобно и с теми оптимизациями которые ему нужны.

Проблема этой статьи еще и в том, что существуют Spectre V1 и Spectre V2, и в части текста автор описывает V2 в то время как код демонстрирует V1, от этого неразбериха в изложении автором принципа работы - они совершенно разные. Ведь тренировка предсказателя переходов это про V2 и программная защита перекомпиляцией кода с использованием retpoline - тоже про V2. В то же время тестовый код это Spectre V1 и перекомпиляция защищаемого п/о принципиально никак не предотвращает эту атаку. Неправильные опции компиляции вредоносного кода конечно поломают его НО только у атакуемого нет никакого способа заставить хакера собрать свой код с такими ключами)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий