Спасибо большое за исследование, может быть теперь мне перестанут люди говорить, что я занимаюсь никому не нужной фигней, пытаясь в UEFI безопасность починить…
Одного только прошу (у авторов оригинального исследования тоже просил, и они обещали исправить) — выкиньте весь вот этот пассаж про SecureBoot:
Первый механизм безопасности, который мог бы заблокировать подобную атаку – это Secure Boot. Когда Secure Boot включен, каждый загружаемый по требованию прошивки компонент самой прошивки должен быть правильно подписан, таким образом гарантируется ее целостность.
UEFI SecureBoot не защищает и не может защищать от атак на прошивку изнутри самой прошивки (всем известная проблема курицы и яйца мешает), он защищает от запуска внешних по отношению к прошивке компонентов — загрузчиков, драйверов, EFI-приложений, т.п.
Если же у вас вредоносный код уже на SPI flash, то отловить его можно только внешними технологиями вроде TPM Measured Boot (который сам по себе тоже можно обойти, но сложнее в разы) и Verified Boot (который должен быть правильно настроен производителем ПК).
Я всеми руками за то, чтобы как можно больше людей включили и пользовались UEFI SecureBoot но создавать ложное чувство уверенности в нем не следует, и от атак такого уровня он не защищает.
Это как сказать, что самолет и есть самолет, чего производители настолько их усложняют? Летали бы дальше на этажерках, которые можно обслуживать одним человеком, и которым не нужно аэропорта, но нет, понавыдумывали Боингов и Аэробусов, в которых черт ногу сломит…
Если серьезно, то современный процессор общего назначения — одна из самых сложны вещей, созданных человеком, на мой взгляд. Там под капотом скрыто управление питанием, управление частотами, управление встроенной периферией, криптография, ускорение специализированных вычислений, куча всего еще, и все это само по себе настолько сложное, что делать это все «на железе», т.е. написанным на Verilog и синтезированным до уровня транзисторных блоков — космически дорого, т.к. любая серьезная ошибка приводила бы к необходимости уничтожения всей партии процессоров и чипсетов с ней.
В итоге вместо этого синтезируется процессор «общего назначения», но попроще, и задача выполняется уже программой для него. Программу можно улучшить без замены самого процессора, программу намного легче отлаживать, программисты дешевле в конце концов. При этом процесс синтеза таких процессорных ядер уже отработан, а свободного места под очередной на кристалле море. Так появился микрокод (там еще не совсем общее назначение, но уже близко), когда декодер операций стало невыносимо писать, потом SMU/PMC (когда невыносимо стало управлять питанием), потом ICC (частотами), потом ME (собрали почти весь разрозненный управляющий софт под одной крышей и запустили в РТОС).
Есть и другая сторона этой медали «переходи на софт или умри» — такой переход резко упрощает реализацию новых идей, и потому вместе с хорошими идеями реализуются и не очень хорошие. Эй пацаны, хотите DRM прямо в чипсете — нате, хотите удаленное управление прямо там же, бесплатно — держите, хотите Java-машину и запуск апплетов прямо там же — пожалуйте, только денег заплатите, чтобы мы вам апплет подписали. А когда ядер много стало свободных, их стали двигать как бесплатный микроконтролер общего назначения, который уже ко всей чипсетной периферии подключен, и который можно программировать, заменив им отдельно стоящий EC/BMC.
Короче, миром опять правит не тайная ложа, а явная лажа. Я не могу отрицать заговора спецслужб или происки марсиан, но я легко могу для себя объяснить нынешнюю ситуацию и без них.
Эта опция (BIOS PSP Support) — такое же отключение PSP, как незапуск HeciDxe — отключение ME. Нормально PSP на процессорах с ним отключить нельзя — он память тренирует и S3 bootscript хранит, так что Intel и в этом плане лучше.
Конфигурацию усложняют, а вот интерфейс к ней — упрощают, и на разнице между v11 и v12 это хорошо видно. Я очень надеюсь, что к них кто-то там понял, что нынешние их технологии просто невозможно настроить так, чтобы в них не зияло дыр, и стал чинить вот это, потому что иначе всем этим технологиям — грош цена.
Мне самому, в принципе, пофигу уже, потому что Т2 закрывает эти вопросы раз и насовсем, но у остальной индустрии Т2 нет, да и у Apple пока что машин с Т2 — три штуки ровно, и они все дорогие.
С такой «успешной» security history всех популярных ОС, можно смело считать, что у локального атакующего эти права уже есть. В конце концов, SecureBoot никто так и не включает, а без него тот же локальный атакующий может загрузить на вашей системе хоть EFI Shell, хоть Linux, и иметь там любые права.
Вот поэтому надо все проверять через MeInfo -verbose, FPT и остальное, а еще лучше эти проверки встроить прямо в прошивку, чтобы она колом вставала при неправильных значениях, либо сама пыталась их исправить, насколько это возможно.
По рукам они бить не могут — руки не настолько длинные, и потому идут по правильному пути, снижая сложность настройки этих технологий, которая до этого была запредельной, а теперь стала просто высокой. Если они этот тренд продолжат, то где-нибудь к МЕv15 вендоры таки смогут (и потому начнут) включать все эти вещи «одной кнопкой», а пока там просто лес стал чуть менее темным.
Таки да? Вот этого я уже не застал, потому что теперь со включенным Manufacturing Mode платформа больше не стартует.
Опять же напомню еще раз, чтобы народ меньше пугался, что ME manufacturing mode умеет выключаться сам, если flash descriptor настроен правильно. К сожалению, это «правильно» по Intel'овски запрещает из региона МЕ чтение, а это портит жизнь довольно сильно, плюс дает Intel ложную уверенность в том, что на MFS можно хранить ключи и их оттуда никто не считает.
В итоге Apple пришлось выключать его вручную только потому, что «правильную» в смысле Intel конфигурацию они не используют, и МЕ у них открыт на чтение.
1. Если у вас все нужное вам работает без драйвера (например, используется внешняя видеокарта и изображение выводится именно ей) — ничего страшного от его недоступности не будет, перестанут работать пару утилит вроде XTU или Clock Commander, но если ими не пользоваться, то драйвер можно не ставить.
2. Обычному пользователю лучше не отключать, потому что вы переводите систему из категории «тестировалась в таком виде производителем» в категорию «не тестировалась никем и никогда», и во второй могут случаться всякие сюрпризы вроде загрузки по 30 секунд и зависаний при попытке обновления прошивки. Если вы энтузиаст и прошивку умеете патчить и обновлять в ручную (а еще вам не нужна встроенная видеокарта или вывод HDCP через нее, и вы не пользуетесь SGX) — можете смело отключать.
Два чая этим авторам, наконец-то описали уязвимость в деталях.
Вообще говоря, проблема не столько в Manufacturing Mode, сколько в возможности отката на уязвимую версию ME v11 несмотря на все попытки со стороны прошивки эту возможность закрыть (если они были вообще, таковые попытки), и если благодаря Максу и Марку Apple удалось убрать возможность локальной эксплуатации, то от физической атаки на МЕ-регион в SPI flash защиты на большинстве систем нет (для машин с ME v11, для которой имеется заведомо уязвимая версия прошивки, от такой атаки защищен только на iMac Pro).
Intel решили проблему с откатом до уязвимых версий в ME v12, добавив Security Version Number в FPF'ы, т.е. после обновления на версию с SVN=X, никакие версии с SVN < X на этой машине больше загрузиться не смогут, т.е. без обхода FPF'ов (а это гораздо более серьезная уязвимость) основную проблему таки получилось решить.
Банковская система в США сильно отличается от европейской или российской, т.к. появилась раньше и развивалась по другим законам и с другими умолчаниями.
Разница в том, что основная операция клиента европейского банка, которую он проводит сам — это перевод денег на определенный чужой счет, и открытые банковские реквизиты нужны для приема платежей, т.е. «отправьте вот эту сумму на этот счет».
В США основная операция — разрешение на снятие определенной суммы со счета в банке отправителя банком получателя, и открытые банковские реквизиты нужны для отправки платежей, т.е. «позвольте снять вот эту сумму вот с этого счета».
Американский банковский чек — это именно разрешение перевести указанную сумму с указанного в чеке счета, при этом куда именно — не важно уже, именно поэтому там нужна подпись, расшифровка суммы словами, названия организации или имя получателя, и подпись отправителя, а вот реквизитов получателя никаких нет.
В итоге простейшая задача отправить кому-то денег превращается в квест, и вокруг квеста каждая компания (Zello, PayPal, Apple, Samsung, etc.) пытается наладить свой небольшой гешефт.
Или, как вариант, это может быть extern const volatile-переменная. Писать в нее можно, но не в этом модуле.
Если программа однопоточная — volatile не нужен, только портит оптимизатору жизнь. Если многопоточная — его недостаточно, от гонок по данным так и не избавились.
Т.е. если там заведомо не регистры, то зачем?
Только не записывать, а читать, потому что записывать мешает const.
Я не про то, что не знаю, зачем оно так, а про то, для чего может понадобится именно extern const volatile, а обычного extern const не хватит, и ничего кроме многопоточной программы и регистров в голову не приходит. В одном потоке переменная (обычная, не отображенная на регистр) из другого юнита меняться не может, т.к. это нарушает инварианты.
Тоже UB и для первого поля, потому что никто не мешает включить sanitizer и memory mapper, который вместо первого поля во все классы воткнет свою структуру, и все полетит к черту.
Отличается тем, что у нее размещение определено, выравнивание определено, и делать его по другому без явного на то указания компилятор не имеет права, и потому макросы вроде OFFSET_OF() и CR() до сих пор отлично работают. У класса (хоть с виртуальными функциями, хоть без) размещение не определено, точнее определяется реализацией, т.е. никто не мешает начать, к примеру, все поля тегировать (т.е. перед каждым полем вставить еще по полю с тегом), сам класс тегировать (вставить ему GUID вначале, чтобы за размещением экземпляров в памяти потом следить), и все это останется в рамках C++ (т.е. код на C++ работать не перестанет), а у вас либо reinterpret_cast вернет непонятно что, либо все завалится еще на ассертах.
Разница в том, где именно происходит проверка на то, что правила доступа не нарушаются, и в C++ она не происходит, потому что вы об этом просите явно очень заметной конструкцией (в Rust таковые еще заметнее), а в JS у вас и соглашение в голове, и проверка его там же, и найти таковые нарушения grep'ом просто так не получится.
Ну таковая передача на C++ невозможна по стандарту даже без разных языков. У языка не определен binary interface, и потому передавать приходится либо структуры из C (у которых таковой интерфейс есть), либо использовать сериализацию в промежуточные форматы вроде protobuf.
Если же использовать особенности конкретных реализаций, то это вновь волшебство, а не C++, потому что даже минорное обновление любого компонента компилятора может вам разломать все в самых неожиданных местах, и про котел в аду там выше не зря написано.
Все равно UB, потому что нет в стандарте никаких гарантий на расположение полей, и завтра в этот класс компилятор вдруг напихает каких-нибудь внутренних структур байт на 20, и все развалится. Даже если оно у вас сейчас работает — это волшебство, а не C++.
У вас переменная уже extern const, оптимизировать ее компилятор уже не будет, потому что она в другом translation unit, и положить ее в регистр если и получится, то только при LTO.
Borrow checker тут при том, что он гарантирует инвариант «доступ к переменной может быть либо из многих мест на чтение, либо из строго одного места на чтение и запись», а конструкция extern const volatile — это как раз про доступ к временной из разных мест на чтение, а для бедных он потому, что хоть и гарантирует, что значение при доступе действительно будет прочитано из переменной каждый раз, но не обеспечивает ни отсутсвие гонки по данным (т.е. чтение во время изменения), ни проверок во время компиляции.
Одного только прошу (у авторов оригинального исследования тоже просил, и они обещали исправить) — выкиньте весь вот этот пассаж про SecureBoot:
UEFI SecureBoot не защищает и не может защищать от атак на прошивку изнутри самой прошивки (всем известная проблема курицы и яйца мешает), он защищает от запуска внешних по отношению к прошивке компонентов — загрузчиков, драйверов, EFI-приложений, т.п.
Если же у вас вредоносный код уже на SPI flash, то отловить его можно только внешними технологиями вроде TPM Measured Boot (который сам по себе тоже можно обойти, но сложнее в разы) и Verified Boot (который должен быть правильно настроен производителем ПК).
Я всеми руками за то, чтобы как можно больше людей включили и пользовались UEFI SecureBoot но создавать ложное чувство уверенности в нем не следует, и от атак такого уровня он не защищает.
Если серьезно, то современный процессор общего назначения — одна из самых сложны вещей, созданных человеком, на мой взгляд. Там под капотом скрыто управление питанием, управление частотами, управление встроенной периферией, криптография, ускорение специализированных вычислений, куча всего еще, и все это само по себе настолько сложное, что делать это все «на железе», т.е. написанным на Verilog и синтезированным до уровня транзисторных блоков — космически дорого, т.к. любая серьезная ошибка приводила бы к необходимости уничтожения всей партии процессоров и чипсетов с ней.
В итоге вместо этого синтезируется процессор «общего назначения», но попроще, и задача выполняется уже программой для него. Программу можно улучшить без замены самого процессора, программу намного легче отлаживать, программисты дешевле в конце концов. При этом процесс синтеза таких процессорных ядер уже отработан, а свободного места под очередной на кристалле море. Так появился микрокод (там еще не совсем общее назначение, но уже близко), когда декодер операций стало невыносимо писать, потом SMU/PMC (когда невыносимо стало управлять питанием), потом ICC (частотами), потом ME (собрали почти весь разрозненный управляющий софт под одной крышей и запустили в РТОС).
Есть и другая сторона этой медали «переходи на софт или умри» — такой переход резко упрощает реализацию новых идей, и потому вместе с хорошими идеями реализуются и не очень хорошие. Эй пацаны, хотите DRM прямо в чипсете — нате, хотите удаленное управление прямо там же, бесплатно — держите, хотите Java-машину и запуск апплетов прямо там же — пожалуйте, только денег заплатите, чтобы мы вам апплет подписали. А когда ядер много стало свободных, их стали двигать как бесплатный микроконтролер общего назначения, который уже ко всей чипсетной периферии подключен, и который можно программировать, заменив им отдельно стоящий EC/BMC.
Короче, миром опять правит не тайная ложа, а явная лажа. Я не могу отрицать заговора спецслужб или происки марсиан, но я легко могу для себя объяснить нынешнюю ситуацию и без них.
Мне самому, в принципе, пофигу уже, потому что Т2 закрывает эти вопросы раз и насовсем, но у остальной индустрии Т2 нет, да и у Apple пока что машин с Т2 — три штуки ровно, и они все дорогие.
По рукам они бить не могут — руки не настолько длинные, и потому идут по правильному пути, снижая сложность настройки этих технологий, которая до этого была запредельной, а теперь стала просто высокой. Если они этот тренд продолжат, то где-нибудь к МЕv15 вендоры таки смогут (и потому начнут) включать все эти вещи «одной кнопкой», а пока там просто лес стал чуть менее темным.
Опять же напомню еще раз, чтобы народ меньше пугался, что ME manufacturing mode умеет выключаться сам, если flash descriptor настроен правильно. К сожалению, это «правильно» по Intel'овски запрещает из региона МЕ чтение, а это портит жизнь довольно сильно, плюс дает Intel ложную уверенность в том, что на MFS можно хранить ключи и их оттуда никто не считает.
В итоге Apple пришлось выключать его вручную только потому, что «правильную» в смысле Intel конфигурацию они не используют, и МЕ у них открыт на чтение.
2. Обычному пользователю лучше не отключать, потому что вы переводите систему из категории «тестировалась в таком виде производителем» в категорию «не тестировалась никем и никогда», и во второй могут случаться всякие сюрпризы вроде загрузки по 30 секунд и зависаний при попытке обновления прошивки. Если вы энтузиаст и прошивку умеете патчить и обновлять в ручную (а еще вам не нужна встроенная видеокарта или вывод HDCP через нее, и вы не пользуетесь SGX) — можете смело отключать.
Вообще говоря, проблема не столько в Manufacturing Mode, сколько в возможности отката на уязвимую версию ME v11 несмотря на все попытки со стороны прошивки эту возможность закрыть (если они были вообще, таковые попытки), и если благодаря Максу и Марку Apple удалось убрать возможность локальной эксплуатации, то от физической атаки на МЕ-регион в SPI flash защиты на большинстве систем нет (для машин с ME v11, для которой имеется заведомо уязвимая версия прошивки, от такой атаки защищен только на iMac Pro).
Intel решили проблему с откатом до уязвимых версий в ME v12, добавив Security Version Number в FPF'ы, т.е. после обновления на версию с SVN=X, никакие версии с SVN < X на этой машине больше загрузиться не смогут, т.е. без обхода FPF'ов (а это гораздо более серьезная уязвимость) основную проблему таки получилось решить.
Следующий пост Брайана можно добавить, хоть он и озаглавлен неудачно:
dtrace.org/blogs/bmc/2018/09/28/the-relative-performance-of-c-and-rust
Разница в том, что основная операция клиента европейского банка, которую он проводит сам — это перевод денег на определенный чужой счет, и открытые банковские реквизиты нужны для приема платежей, т.е. «отправьте вот эту сумму на этот счет».
В США основная операция — разрешение на снятие определенной суммы со счета в банке отправителя банком получателя, и открытые банковские реквизиты нужны для отправки платежей, т.е. «позвольте снять вот эту сумму вот с этого счета».
Американский банковский чек — это именно разрешение перевести указанную сумму с указанного в чеке счета, при этом куда именно — не важно уже, именно поэтому там нужна подпись, расшифровка суммы словами, названия организации или имя получателя, и подпись отправителя, а вот реквизитов получателя никаких нет.
В итоге простейшая задача отправить кому-то денег превращается в квест, и вокруг квеста каждая компания (Zello, PayPal, Apple, Samsung, etc.) пытается наладить свой небольшой гешефт.
Если программа однопоточная — volatile не нужен, только портит оптимизатору жизнь. Если многопоточная — его недостаточно, от гонок по данным так и не избавились.
Т.е. если там заведомо не регистры, то зачем?
Я не про то, что не знаю, зачем оно так, а про то, для чего может понадобится именно extern const volatile, а обычного extern const не хватит, и ничего кроме многопоточной программы и регистров в голову не приходит. В одном потоке переменная (обычная, не отображенная на регистр) из другого юнита меняться не может, т.к. это нарушает инварианты.
Разница в том, где именно происходит проверка на то, что правила доступа не нарушаются, и в C++ она не происходит, потому что вы об этом просите явно очень заметной конструкцией (в Rust таковые еще заметнее), а в JS у вас и соглашение в голове, и проверка его там же, и найти таковые нарушения grep'ом просто так не получится.
Если же использовать особенности конкретных реализаций, то это вновь волшебство, а не C++, потому что даже минорное обновление любого компонента компилятора может вам разломать все в самых неожиданных местах, и про котел в аду там выше не зря написано.
Borrow checker тут при том, что он гарантирует инвариант «доступ к переменной может быть либо из многих мест на чтение, либо из строго одного места на чтение и запись», а конструкция extern const volatile — это как раз про доступ к временной из разных мест на чтение, а для бедных он потому, что хоть и гарантирует, что значение при доступе действительно будет прочитано из переменной каждый раз, но не обеспечивает ни отсутсвие гонки по данным (т.е. чтение во время изменения), ни проверок во время компиляции.