Вы используете устаревший браузер!

Страница может отображаться некорректно.

  • добавить в избранное
    Добавить в закладки

Уязвимое железо

Прочитали: 3269 Комментариев: 103 Рейтинг: 106

Пачка новогодних новостей о найденных уязвимостях в самых разных процессорах привела к изрядной панике. Программисты всего мира в праздники были вынуждены срочно анализировать уязвимости и искать способы защититься. Что же было обнаружено?

На самом деле уязвимостей было найдено три: одну назвали Meltdown (CVE-2017-5754), а две других получили общее наименование Spectre (CVE-2017-5753 и CVE-2017-5715). Для простоты рассмотрим только первую из трех.

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

Приложения вместо прямого доступа к физической памяти получают виртуальные адресные пространства, отображаемые на физическую память так, что пространства разных приложений не пересекаются. Контроль за адресными пространствами реализован аппаратно — блоком MMU, Memory Management Unit.

https://geektimes.ru/post/297029

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

Предположим, вы идете по улице. Чтобы попасть из пункта А в пункт Б, вам нужно последовательно сделать N шагов. Вы совершаете одну и ту же последовательность действий – шаг за шагом. При этом вполне можно предсказать, что, если вы сделали шаг из точки А1 в точку А2, то вы, скорее всего, сделаете полностью аналогичные шаги из А2 в А3, из А3 в А4 и т. д.А вот если бы вы могли сразу сделать все шаги за один шаг – вы могли бы мгновенно оказаться в пункте Б!

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

Например:

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

https://geektimes.ru/post/297029

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

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

Если MMU сообщает, что код некорректен, в эту память нельзя — процессор просто сбрасывает все насчитанное.

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

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

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

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

Допустим, приложению доступны адреса 0...9999, а ядру — 10000...20000, цифры тут неважны. И мы делаем конструкцию, расположенную в коде так, что процессор заведомо выполнит её в спекулятивном режиме (например, на тысячном повторении одного и того же цикла, 999 предыдущих повторений которого выполнялись корректно), и которая будет представлять собой косвенную адресацию по значению, лежащему по адресу 15000.

  1. Процессор в спекулятивном режиме читает значение по адресу 15000. Пусть там будет лежать, например, 98 (действие, выполняемое заранее, в ходе которого запрашиваются данные, которые приложению по идее недоступны – мы помним, что приложению доступны адреса 0...9999).
  2. Процессор читает значение, лежащее по адресу 98 (значение, лежащее по адресу 15000).
  3. От MMU приходит ответ о невалидности адреса 15000 (помним, что вычисления производятся ранее проверки на реальную доступность данных).
  4. Процессор сбрасывает конвейер и вместо значения, лежащего по адресу 98, выдаёт нам ошибку.
  5. Наше приложение начинает читать адреса от 0 и выше в собственном адресном пространстве (имеет полное право), замеряя время, требующееся на чтение каждого адреса, и читая их не по порядку, чтобы не натренировать тот же спекулятивный доступ.
  6. На адресе 98 время доступа вдруг оказывается в несколько раз ниже, чем на других адресах.

Таким образом мы понимаем, что кто-то уже недавно читал что-то по этому адресу, в результате чего он попал в кэш. Кто бы это мог быть? Ах да, это наш дорогой процессор. По адресу 15000, соответственно, лежит значение 98.

Таким образом мы можем прочитать всю память ядра системы, на которую, в свою очередь, в современных ОС отображается вообще вся физическая память компьютера.

Или проще:

— Дед, люди говорят, у тебя винтовка в подполе лежит?
— Брешут.
— Дед, люди говорят, у тебя в огороде пулемет прикопан?
— Брешут.
— Дед, говорят, у нас в садочке танк захован.
— Брешут.
— Дед, говорят, на чердаке атомная бомба висит.
— (Притормозив, так как такое чудо вроде как не смазывал маслом для сохранности) Брешут.

Кто подвержен Meltdown?

Как минимум все процессоры Intel линейки Core, все процессоры Intel линейки Xeon, все процессоры Intel линеек Celeron и Pentium на ядрах семейства Core.

Также подвержены уязвимости процессоры на ядрах ARM Cortex-A75, на которых, однако, пока что не выпущено каких-либо конечных устройств, а первый процессор — Qualcomm Snapdragon 845 на ядре Kryo 385, основанном на Cortex-A75 и Cortex-A53, — объявлен только месяц назад. Скорее всего, Kryo 385 также будет уязвим к Meltdown.

Согласно заявлению Apple, «все iOS-устройства» подвержены Meltdown. Это, очевидно, не может относиться к вообще всем когда-либо использовавшимся в iPhone/iPad процессорам (в конце концов, какой-нибудь iPhone 4 использует стандартное ядро Cortex-A8), но ARM-процессоры в современных моделях iPhone и iPad можно считать уязвимыми.

Подробнее – по ссылкам: https://geektimes.ru/post/297029 и https://geektimes.ru/post/297031.

#уязвимость #эксплойт

Dr.Web рекомендует

Ситуация пугающая, однако есть несколько «но».

  1. Найденные уязвимости не позволяют злоумышленнику получить удаленный доступ к системе. Для эксплуатации уязвимости вредоносный файл должен быть сначала загружен в систему. А значит, антивирус и ограничение прав на установку приложений – наши лучшие друзья для защиты процессоров.
  2. Патчи, защищающие от Meltdown, переносят область памяти ядра в другую область, в результате чего данные разделяются не только контролем на аппаратном уровне (который, увы, пал), но и разделением контроля доступа по адресам. Поскольку контроль переходит от аппаратной части к программной, приложения при выполнении системных вызовов замедляются. Но есть нюанс. Пользовательским приложениям системные вызовы не особо нужны. Поэтому, по имеющимся данным, в играх замедления практически нет, и ставить патч можно без опасений. А для серверов защита может состоять в их полной изоляции. Нет новых файлов – нет и возможности использования уязвимости. Но лучше и там поставить патч.
    На синтетических тестах у вас действительно могут быть просадки на 30%, но на реальной системе, даже на той, которая активно использует системные вызовы, у вас будет просадка меньше, есть еще сеть, память, и все это будет влиять. В масштабах дата-центров класса GCP, AWS, FB доля таких сервером далеко не подавляющая, что и приводит к общей потере производительности, измеряемой числами порядка единиц процентов. Под удар попадут клиенты, у которых основная масса серверов оказалась подвержена деградации производительности, но таких, вероятно, довольно мало.

    Для тех кто использует браузер Mozilla Firеfox:
    Mozilla предоставила временное решение вопроса в версии браузера Firеfox 57. По словам компании, оно призвано затруднить проведение атаки с использованием Meltdown и Spectre - https://drw.sh/dsubnp Соответственно тем, кто использует браузер Mozilla Firefox настоятельно рекомендуется обновить его до последней версии.

    Для тех кто использует браузер Google Chrome:
    1) либо временно отказаться от его использования ориентировочно до 23 января или до появления 64-й версии (примерно 23 января соответствующий патч будет включен в обновление, с выходом 64-й версии Google Chrome) - https://drw.sh/xsfwmz
    2) либо (на свой страх и риск, разумеется) включить тестовую функцию защиты от уязвимостей в Google Chrome, перейдя на страницу скрытых настроек chrome://flags/#enable-site-per-process и активировав опцию Strict site isolation и перезагрузить браузер - https://drw.sh/yjrlpf

    Для тех кто использует Яндекс Браузер:
    1) либо временно отказаться от использования браузера до выхода новой версии с исправлением уязвимости
    2) либо (опять же на свой страх и риск) включить изоляцию данных: набрать в Умной строке адрес browser://flags/#enable-site-per-process. Далее нажать клавишу Enter. Под описанием опции Strict site isolation нажать ссылку Включить. В нижней части экрана нажать появившуюся кнопку Перезапустить сейчас - https://drw.sh/oxknrw

  3. Javascript в браузерах по умолчанию должен быть выключен.

Благодарим участника проекта Littlefish за ценное дополнение.

Получайте Dr.Web-ки за участие в проекте

Каждая активность = 1 Dr.Web-ка

Оцените выпуск

Сделайте репост

Поставьте «Нравится»

Чтобы получать награды надо войти на страницу выпуска через аккаунт на сайте «Доктор Веб» (или создать аккаунт). Аккаунт должен быть связан с вашим аккаунтом в социальной сети. Видео о связывании аккаунта.


Нам важно ваше мнение

10 Dr.Web-ок за комментарий в день выхода выпуска или 1 Dr.Web-ка в любой другой день. Комментарии публикуются автоматически и постмодерируются. Правила комментирования новостей «Доктор Веб».

Чтобы оставить комментарий, нужно зайти через свой аккаунт на сайте «Доктор Веб». Если аккаунта еще нет, его можно создать.

Комментарии пользователей


 
На страницу: