После небольшого перерыва продолжаем разговор о безопасности UEFI. В этот раз речь пойдет о технологии SecureBoot, ее преимуществах и недостатках, об атаках на нее и защите от них.
Впервые о SecureBoot речь зашла в стандарте UEFI 2.2 в 2011 году, но окончательно все аспекты были реализованы в версии 2.3.1C в начале 2012 года. Основным разработчиком технологии была Microsoft, которая сразу же заявила, что для получения сертификата Windows 8 Ready для своей еще не выпущенной новой ОС требуется реализация и включение SecureBoot по умолчанию на всех новых ПК. Это заявление вызвало волну резкой критики со стороны сторонников свободного ПО, которая успешно докатилась и до Хабра.
Если вам интересно, чем именно закончилось противостояние MS и сообщества, как SecureBoot выглядит после почти 4 лет взросления, и какие атаки на него все еще возможны — добро пожаловать под кат.
Стоп, чуть не забыл: по доброй традиции, набор ссылок на предыдущие части, для тех, кто умудрился их пропустить.
Не думаю, что после десятка статей на Хабре стоит рассказывать о SecureBoot слишком уж подробно — это уже было сделано не раз и без меня. Тем не менее, совсем ничего не рассказать было бы преступлением против незнакомого с темой читателя, поэтому пройдемся по верхам, а желающих знать все и досконально привычно отправим в спецификацию.
SecureBoot — это программная технология, при помощи которой UEFI-совместимая прошивка может проверить подлинность исполняемых ей внешних компонентов (загрузчиков, драйверов и UEFI OptionROM'ов). Эти исполняемые компоненты должны быть подписаны ЭЦП, которая проверяется во время загрузки и в случае ее полного отсутствия, повреждения, отсутствия в списке доверенных (db) или присутствия в списке запрещенных (dbx) запуск соответствующего компонента не происходит (иногда это поведение настраивается, что тоже может сыграть злую шутку, но об этом позже). В качестве алгоритма ЭЦП в данный момент стандартом рекомендуется комбинация из RSA2048 и SHA256, которые и используются почти на всех виденных мной в живую системах.
SecureBoot использует следующую иерархию ключей:
На вершине находится PK — главный ключ, устанавливающий доверительные отношения между пользователем платформы и ее прошивкой. Состоит он, как и любой ключ RSA, из открытого ключа PKpub и закрытого ключа PKpriv и хранится в NVRAM в виде self-signed сертификата. Обладателя закрытой части PKpriv спецификация не без оснований называет хозяином платформы.
В зависимости от необходимого уровня безопасности, PK может быть сгенерирован следующим образом:
Изначально PK генерируется производителем платформы, и сам не участвует подписывании и проверке подписей исполняемых компонентов, а используется для управления хранилищем ключей KEK. Обладателя KEKpriv спецификация называет авторизованным пользователем. Каждый ключ KEK устанавливает доверительные отношения между производителем исполняемого компонента и прошивкой. Эти ключи используются для управления хранилищами db (где лежат сертификаты и хеши разрешенных к запуску компонентов), и dbx (куда обладатель KEKpriv может внести сертификаты и хеши компонентов, запуск которых необходимо запретить несмотря на правильную подпись).
В большинстве конфигураций SecureBoot по умолчанию PK предоставляется производителем мат. платы, в KEK лежит единственный сертификат Microsoft Corporation KEK CA 2011, а в db обязательно присутствует сертификат Microsoft Windows Production CA 2011, но иногда к нему добавляют сертификат Canonical и сертификат производителя платформы, которым подписаны разного рода утилиты для обновления прошивки и вот это все. Хранилище dbx на большинстве систем пустое, но не так давно MS внесли в него несколько записей и теперь требуют их наличия на новых системах для получения сертификата Windows 10 Ready. Получается, что с точки зрения SecureBoot в конфигурации по умолчанию, вашей системой владеет производитель мат. платы, а единственный ее авторизованный пользователь — Microsoft. К счастью (и по большей части благодаря давлению сообщества СПО) эта печальная картина на подавляющем большинстве систем для x86 может быть разрушена удалением стандартных ключей и добавлением собственных из BIOS Setup, но про это я планирую написать отдельно.
Осталось упомянуть, что SecureBoot не совместим и не должен быть включен совместно с CSM, т.е. если вы до сих пор используете старые ОС, не умеющие загружаться без CSM, то от SecureBoot вам толку не будет ни в каком виде. Самое интересное, что MS до сих пор не желает добавить в Windows 7 поддержку GOP, а без нее загрузка этой ОС без CSM либо вообще не работает, либо происходит «вслепую», что практически наверняка делает Windows 7 несовместимой с SecureBoot, даже если пользователь самостоятельно подпишет загрузчик для нее. Доля же Windows 7 в корпоративном сегменте намного превышает долю более новых ОС, и потому системы с включенной SecureBoot по прежнему малопопулярны там, где она действительно была бы полезна.
Для начала следует понять, какие именно части SecureBoot могут быть атакованы и чем грозит успешная атака:
Если у атакующего имеется доступ на запись в хранилище NVRAM, что нередко случается у любителей защитить микросхему SPI лишь при помощи пары PR-регистров, то текущий PK можно банально удалить, что автоматически отключит SecureBoot, переведя его в режим установки новых ключей.
Эта атака — комбинация из атаки на NVRAM и реализацию. На некоторых системах текущий режим SecureBoot управляется записью в переменной Setup, и если она неожиданно для всех имеет флаг RT, то атакующий может отключить SecureBoot просто записав в Setup ноль по нужному смещению, которое, в свою очередь, легко можно найти анализом дампа IFR. Атака тупая как валенок, но до сих пор имеется куча систем, которые ей подвержены.
Вариация предыдущей атаки, но отключается на этот раз не сам SecureBoot, а запрет на продолжение загрузки при несовпадении или отсутствии ЭЦП. Тоже требует флага RT на переменной Setup и встречается чуть реже, чем предыдущий вариант, но зато позволяет обойти SecureBoot тихо, не отключая его.
На некоторых системах для обхода SecureBoot достаточно немного испортить NVRAM (к примеру, заполнив хранилище под завязку), чтобы отключить либо обойти SecureBoot. Встречается такое поведение редко, но атака настолько простая, что есть смысл опробовать ее на любой системе. В крайнем случае, вместо обхода SecureBoot может получиться DoS, если драйвер NVRAM совсем плохой.
Теоретически, запуск UEFI OptionROM'ов из PCI-устройств при включенном SecureBoot не должен происходить, если соответствующий OROM не прошел верификацию, но на практике огромно количество систем доверяет PCI-устройствам безоговорочно и запускает оттуда все без каких-либо проверок. Примеров подобного поведения много, а любые системы без SecureBoot подвержены такой атаке автоматически, именно поэтому вынос PCI(e) на внешние разъемы, вроде Thunderbolt, Firewire, PCMCIA, ExpressCard и т.п. — преступление против безопасности платформы, даже без учета того, что любое PCI-устройство может инициировать DMA с любым регионом физической памяти, кроме SMRAM (и то только если производитель платформы не забыл установить защиту) и утащить у ОС и пользователя все их секреты.
Старая атака на реализацию, которой внезапно оказалось подвержена добрая половина реализаций (следствие того, что почти все IBV используют эталонную реализацию из TianoCore). Суть атаки: UEFI-загрузчик и вообще любой исполняемый файл UEFI может быть либо в формате PE, либо в формате TE (который, по факту, тот же самый PE, только с обрезанными заголовками, чтобы места в кэше занималось меньше). Формат TE очень редко используется для каких-то компонентов прошивки, кроме PEI-модулей (т.к. только в первой половине PEI, до инициализации RAM, есть смысл экономить 240h байт на заголовке), и потому эталонная реализация проверки ЭЦП не проверяла ее у образов в формате TE вообще, а вследствие комбинации двух мелких ошибок проверка такого образа всегда заканчивалась успехом. Преобразование PE ->TE тривиально, и SecureBoot можно было обойти лишь небольшим изменением файла с загрузчиком, поэтому проблема была признана серьезной и быстро исправлена. Тем не менее, до сих пор имеется куча старых систем с этой проблемой, и потому об этой атаке все еще помнят.
Это даже не совсем атака, а скорее непонимание некоторых пользователей, что SecureBoot вообще не защищает от подмены загрузчика, и физически присутствующий атакующий может загрузить систему со своего носителя. Иногда от этого пытаются защититься паролем на BIOS и меню выбора загрузочного устройства, но добрые разработчики из MS позволяют выбрать его и из Windows, для чего достаточно зажать Shift и выбрать действие «перезагрузка» на экране входа в систему, а затем выбрать в появившемся меню нужно загрузочное устройство. Дорогим товарищам из MS — мое большое спасибо.
Ну вот, с SecureBoot худо-бедно разобрались, в следующей (надеюсь, что заключительной) части поговорим о ПО и персоналиях.
Спасибо за внимание, стойкого вам SecureBoot'а.
Впервые о SecureBoot речь зашла в стандарте UEFI 2.2 в 2011 году, но окончательно все аспекты были реализованы в версии 2.3.1C в начале 2012 года. Основным разработчиком технологии была Microsoft, которая сразу же заявила, что для получения сертификата Windows 8 Ready для своей еще не выпущенной новой ОС требуется реализация и включение SecureBoot по умолчанию на всех новых ПК. Это заявление вызвало волну резкой критики со стороны сторонников свободного ПО, которая успешно докатилась и до Хабра.
Если вам интересно, чем именно закончилось противостояние MS и сообщества, как SecureBoot выглядит после почти 4 лет взросления, и какие атаки на него все еще возможны — добро пожаловать под кат.
Стоп, чуть не забыл: по доброй традиции, набор ссылок на предыдущие части, для тех, кто умудрился их пропустить.
Часть пятая. SecureBoot
Это что вообще?
Не думаю, что после десятка статей на Хабре стоит рассказывать о SecureBoot слишком уж подробно — это уже было сделано не раз и без меня. Тем не менее, совсем ничего не рассказать было бы преступлением против незнакомого с темой читателя, поэтому пройдемся по верхам, а желающих знать все и досконально привычно отправим в спецификацию.
SecureBoot — это программная технология, при помощи которой UEFI-совместимая прошивка может проверить подлинность исполняемых ей внешних компонентов (загрузчиков, драйверов и UEFI OptionROM'ов). Эти исполняемые компоненты должны быть подписаны ЭЦП, которая проверяется во время загрузки и в случае ее полного отсутствия, повреждения, отсутствия в списке доверенных (db) или присутствия в списке запрещенных (dbx) запуск соответствующего компонента не происходит (иногда это поведение настраивается, что тоже может сыграть злую шутку, но об этом позже). В качестве алгоритма ЭЦП в данный момент стандартом рекомендуется комбинация из RSA2048 и SHA256, которые и используются почти на всех виденных мной в живую системах.
Немного о ключах
SecureBoot использует следующую иерархию ключей:
На вершине находится PK — главный ключ, устанавливающий доверительные отношения между пользователем платформы и ее прошивкой. Состоит он, как и любой ключ RSA, из открытого ключа PKpub и закрытого ключа PKpriv и хранится в NVRAM в виде self-signed сертификата. Обладателя закрытой части PKpriv спецификация не без оснований называет хозяином платформы.
В зависимости от необходимого уровня безопасности, PK может быть сгенерирован следующим образом:
- Собственный ключ для каждого отдельного ПК. Максимальная безопасность, она же — максимальный геморрой с управлением ключами, зато и утечки практически не страшны, и компрометация системы с утекшим ключом не ведет к компрометации соседней с ней.
- Общий ключ для каждой модели мат. платы. Менее безопасно, но проще в обслуживании, особенно если парк машин собран на одних и тех же платах.
- Общий ключ каждой линейки мат. плат. То же самое, что и в предыдущем пункте, еще немного меньшая безопасность по цене чуть большего удобства, классический случай security-convenience trade-off.
- Общий ключ для всех плат производителя. Самое нелепое с точки зрения безопасности, но при этом, к сожалению, чуть ли не самое популярное решение. Ключ при этом хранится прямо в дереве исходных текстов и утекает вместе с ними, после чего никакой SecureBoot на платах этого производителя уже не помеха. При этом исходники чаще всего утекают тихо, и производитель может еще пару лет выпускать заведомо уязвимую продукцию.
Изначально PK генерируется производителем платформы, и сам не участвует подписывании и проверке подписей исполняемых компонентов, а используется для управления хранилищем ключей KEK. Обладателя KEKpriv спецификация называет авторизованным пользователем. Каждый ключ KEK устанавливает доверительные отношения между производителем исполняемого компонента и прошивкой. Эти ключи используются для управления хранилищами db (где лежат сертификаты и хеши разрешенных к запуску компонентов), и dbx (куда обладатель KEKpriv может внести сертификаты и хеши компонентов, запуск которых необходимо запретить несмотря на правильную подпись).
Кто тут в цари первый?
В большинстве конфигураций SecureBoot по умолчанию PK предоставляется производителем мат. платы, в KEK лежит единственный сертификат Microsoft Corporation KEK CA 2011, а в db обязательно присутствует сертификат Microsoft Windows Production CA 2011, но иногда к нему добавляют сертификат Canonical и сертификат производителя платформы, которым подписаны разного рода утилиты для обновления прошивки и вот это все. Хранилище dbx на большинстве систем пустое, но не так давно MS внесли в него несколько записей и теперь требуют их наличия на новых системах для получения сертификата Windows 10 Ready. Получается, что с точки зрения SecureBoot в конфигурации по умолчанию, вашей системой владеет производитель мат. платы, а единственный ее авторизованный пользователь — Microsoft. К счастью (и по большей части благодаря давлению сообщества СПО) эта печальная картина на подавляющем большинстве систем для x86 может быть разрушена удалением стандартных ключей и добавлением собственных из BIOS Setup, но про это я планирую написать отдельно.
Несовместимость с CSM
Осталось упомянуть, что SecureBoot не совместим и не должен быть включен совместно с CSM, т.е. если вы до сих пор используете старые ОС, не умеющие загружаться без CSM, то от SecureBoot вам толку не будет ни в каком виде. Самое интересное, что MS до сих пор не желает добавить в Windows 7 поддержку GOP, а без нее загрузка этой ОС без CSM либо вообще не работает, либо происходит «вслепую», что практически наверняка делает Windows 7 несовместимой с SecureBoot, даже если пользователь самостоятельно подпишет загрузчик для нее. Доля же Windows 7 в корпоративном сегменте намного превышает долю более новых ОС, и потому системы с включенной SecureBoot по прежнему малопопулярны там, где она действительно была бы полезна.
Атаки на SecureBoot
О векторах
Для начала следует понять, какие именно части SecureBoot могут быть атакованы и чем грозит успешная атака:
- NVRAM. Так как и PK, и KEK, и db и dbx, и другие относящиеся к SecureBoot переменные хранятся в NVRAM, то успешная атака на нее чаще всего приводит к отключению или компрометации SecureBoot.
- Реализация. Если с NVRAM все в порядке, проблемы могут быть в реализации проверки подписи, хранения ключей и т.п.
- Ключи. Атака одновременно и сложная, и простая. Всего-то надо стащить у кого-нибудь из цепочки доверия его закрытый ключ и подписать им свой вредоносный загрузчик.
- Доверенный загрузчик. Еще проще, чем предыдущий пункт, особенно для обладателей сертификата Canonical в db. Просто меняем текущий загрузчик на подписанный вышеупомянутым сертификатом GRUB2 из репозиториев Ubuntu, который в свою очередь загрузит что угодно любой степени вредоносности.
Собственно атаки
Отключение SecureBoot удалением PK
Если у атакующего имеется доступ на запись в хранилище NVRAM, что нередко случается у любителей защитить микросхему SPI лишь при помощи пары PR-регистров, то текущий PK можно банально удалить, что автоматически отключит SecureBoot, переведя его в режим установки новых ключей.
Отключение SecureBoot правкой CurrentMode
Эта атака — комбинация из атаки на NVRAM и реализацию. На некоторых системах текущий режим SecureBoot управляется записью в переменной Setup, и если она неожиданно для всех имеет флаг RT, то атакующий может отключить SecureBoot просто записав в Setup ноль по нужному смещению, которое, в свою очередь, легко можно найти анализом дампа IFR. Атака тупая как валенок, но до сих пор имеется куча систем, которые ей подвержены.
Обход SecureBoot правкой ExecutionPolicy
Вариация предыдущей атаки, но отключается на этот раз не сам SecureBoot, а запрет на продолжение загрузки при несовпадении или отсутствии ЭЦП. Тоже требует флага RT на переменной Setup и встречается чуть реже, чем предыдущий вариант, но зато позволяет обойти SecureBoot тихо, не отключая его.
Обход SecureBoot повреждением NVRAM
На некоторых системах для обхода SecureBoot достаточно немного испортить NVRAM (к примеру, заполнив хранилище под завязку), чтобы отключить либо обойти SecureBoot. Встречается такое поведение редко, но атака настолько простая, что есть смысл опробовать ее на любой системе. В крайнем случае, вместо обхода SecureBoot может получиться DoS, если драйвер NVRAM совсем плохой.
Обход SecureBoot при помощи PCI(e)-устройства
Теоретически, запуск UEFI OptionROM'ов из PCI-устройств при включенном SecureBoot не должен происходить, если соответствующий OROM не прошел верификацию, но на практике огромно количество систем доверяет PCI-устройствам безоговорочно и запускает оттуда все без каких-либо проверок. Примеров подобного поведения много, а любые системы без SecureBoot подвержены такой атаке автоматически, именно поэтому вынос PCI(e) на внешние разъемы, вроде Thunderbolt, Firewire, PCMCIA, ExpressCard и т.п. — преступление против безопасности платформы, даже без учета того, что любое PCI-устройство может инициировать DMA с любым регионом физической памяти, кроме SMRAM (и то только если производитель платформы не забыл установить защиту) и утащить у ОС и пользователя все их секреты.
Обход SecureBoot преобразованием загрузчика из PE в TE
Старая атака на реализацию, которой внезапно оказалось подвержена добрая половина реализаций (следствие того, что почти все IBV используют эталонную реализацию из TianoCore). Суть атаки: UEFI-загрузчик и вообще любой исполняемый файл UEFI может быть либо в формате PE, либо в формате TE (который, по факту, тот же самый PE, только с обрезанными заголовками, чтобы места в кэше занималось меньше). Формат TE очень редко используется для каких-то компонентов прошивки, кроме PEI-модулей (т.к. только в первой половине PEI, до инициализации RAM, есть смысл экономить 240h байт на заголовке), и потому эталонная реализация проверки ЭЦП не проверяла ее у образов в формате TE вообще, а вследствие комбинации двух мелких ошибок проверка такого образа всегда заканчивалась успехом. Преобразование PE ->TE тривиально, и SecureBoot можно было обойти лишь небольшим изменением файла с загрузчиком, поэтому проблема была признана серьезной и быстро исправлена. Тем не менее, до сих пор имеется куча старых систем с этой проблемой, и потому об этой атаке все еще помнят.
Обход SecureBoot загрузкой с внешнего носителя
Это даже не совсем атака, а скорее непонимание некоторых пользователей, что SecureBoot вообще не защищает от подмены загрузчика, и физически присутствующий атакующий может загрузить систему со своего носителя. Иногда от этого пытаются защититься паролем на BIOS и меню выбора загрузочного устройства, но добрые разработчики из MS позволяют выбрать его и из Windows, для чего достаточно зажать Shift и выбрать действие «перезагрузка» на экране входа в систему, а затем выбрать в появившемся меню нужно загрузочное устройство. Дорогим товарищам из MS — мое большое спасибо.
Заключение
Ну вот, с SecureBoot худо-бедно разобрались, в следующей (надеюсь, что заключительной) части поговорим о ПО и персоналиях.
Спасибо за внимание, стойкого вам SecureBoot'а.