Возможности uefi для реализации функций защиты информации
В статье рассматриваются основные фазы загрузки базовой системы ввода-вывода, способы встраивания исполняемых образов в различные фазы загрузки UEFI и способы защиты от вредоносного кода в UEFI BIOS.
Ключевые слова: UEFI BIOS, DXE Phase, PEI Phase, Boot Firmware Volume (BFV), DXE Core.
UEFI boot stages and ways to control executable images
The article describes the UEFI boot phases, the ways of embedding executable images in various phases, and ways how to protect against malicious code in the UEFI BIOS.
Keywords: UEFI BIOS, DXE Phase, PEI Phase, Boot Firmware Volume (BFV), DXE Core.
Базовая система ввода-вывода (BIOS) давно перестала быть простейшей микропрограммой, главной целью которой является инициализация и тестирование на низком уровне аппаратных компонентов компьютера для дальнейшей передачи управления загрузчику операционной системы (ОС). С момента введения единого расширяемого микропрограммного интерфейса (Unified Extensible Firmware Interface, UEFI) BIOS приобретает черты упрощенной современной операционной системы со своими фазами загрузки и механизмами обеспечения безопасности, включая реализацию различных криптографических функций [1]. UEFI также позволяет расширять прошивку платформы, загружая исполняемые образы – драйверы или приложения. Исполняемые образы представляют собой класс файлов, определенных спецификацией UEFI, которые содержат исполняемый код. Загруженные образы получают доступ к сервисам, которые также определены спецификацией UEFI (boot services, runtime services) [2. С. 31]. Исполняемые образы могут быть загружены в память как встроенным менеджером загрузки, так и другими исполняемыми образами [3. С. 17]. Данная возможность позволяет расширять функционал базовой системы ввода-вывода, однако, она создает новые векторы атак в случае неконтролируемого встраивания драйверов.
Существуют штатные механизмы защиты от этих атак. Однако практическая реализация этих механизмов может защитить не от всех атак, а нарушение организационных требований может привести к неэффективности использования штатных средств защиты.
Внедрение в BIOS дает возможность распространить влияние вредоносного кода на все последующие этапы загрузки. Под угрозой оказываются код управления системой (System Management Mode, SMM), существующие средства защиты, загрузчики, гипервизор и операционная система (ОС). Учитывая, что BIOS запускается с высоким уровнем привилегий на одном из первых этапов загрузки ЭВМ, вредоносный код, исполняемый на уровне BIOS, очень сложно детектировать и устранить на последующих этапах. Для понимания способов инъекций вредоносного кода в UEFI и защиты от них, необходимо ознакомиться со всеми фазами загрузки и возможностями инъекции кода в каждую из них.
Согласно спецификации UEFI система проходит следующие этапы загрузки: Security (Sec), Pre EFI Initialization (PEI), Driver Execution Environment (DXE), Boot Dev Select (BDS) [2. С. 11].
Внедрение в фазу Security невозможно из-за проприетарности данной стадии. В данной фазе подготавливается временная память, адрес и размер которой передаются в фазу PEI. Помимо этого в фазу PEI передается адрес и размер стека, состояние платформы, адрес и размер BFV (Boot Firmware Volume) [4].
В фазе PEI инициализируется RAM для запуска фазы DXE. В фазу DXE передается информация об обнаруженных устройствах для корректной инициализации каждого из устройств. Фаза PEI состоит из ядра и модулей PEIM, осуществляющих первичную инициализацию устройств. Список PEIM может быть расширен путем добавления собственных модулей. Ядро PEI обходит все тома прошивки в поиске всех PEI модулей и запускает их. Порядок запуска модулей не случаен и определяется диспетчером PEI. Модули могут иметь зависимости от других модулей, поэтому сперва запускаются модули, не имеющие зависимостей, затем модули, зависящие от них по цепочке [4].
Код DXE состоит из ядра (DXE Core), диспетчера и драйверов. Ядро инициализирует и запускает службы UEFI. Диспетчер осуществляет поиск всех DXE-драйверов и передачу управления каждому из них. Данные драйверы могут содержать зависимости от других компонентов. Каждый DXE-модуль может осуществлять загрузку и запуск исполняемых образов, одним из которых может выступать загрузчик ОС. После исполнения драйверов осуществляется поиск загрузчика ОС [4].
Таким образом, инъекция драйвера как в фазу PEI, так и в DXE может нарушить процесс загрузки ОС, запустив исполняемый образ в UEFI. Рассмотрим практический способ влияния на процесс загрузки на примере инъекции вредоносного DXE-драйвера с использованием утилиты UEFI Tool и программатора. UEFI Tool позволяет считывать и редактировать бинарный файл прошивки (BFV), расширяя его исполняемым кодом и различными данными. В качестве примера приведем сценарий встраивания и функционирования вредоносного драйвера в одной из фаз.
Стоит отметить, что такой драйвер может иметь как примитивный вид, так и представлять собой многофункциональный программный компонент. Для простоты понимания можно ввести допущение, что загружаемый исполняемый образ расположен в корне одной из файловых систем. Данное допущение не уменьшает значимости данного вектора атаки на BIOS, так как исполняемый образ может быть загружен в систему в режиме выполнения самим драйвером, содержащего вредоносный код. Получив список всех файловых систем, драйвер осуществит проверку наличия необходимого образа и, в случае успеха, загрузит код в память и передаст ему управление. Стоит заметить, что для поиска исполняемого образа в коде драйвера могут использоваться протоколы. Как было сказано выше, порядок получения управления различными драйверами строго не определен, а это значит, что на момент выполнения используемые протоколы могут быть еще не доступны для использования. Для обеспечения доступности используемых протоколов необходимо использовать секцию [Depex]. В данной секции указывается список протоколов, использование которых необходимо разрабатываемому драйверу. Эта секция обеспечит получение драйвером управления только тогда, когда системные службы или другие драйверы предоставят доступ к использованию необходимых протоколов, указанных в этой секции.
Считав программатором с чипа бинарный файл прошивки, злоумышленник может приступить к ее модификации. Полученные после сборки исходного кода драйвера файлы необходимо обернуть в определенный формат и добавить в один из томов прошивки системы. Злоумышленник успешно завершит атаку, записав программатором модифицированный бинарный файл на чип обратно.
Рассмотренный способ влияния на процесс загрузки подтверждает необходимость проверки каждого из DXE-драйверов, получающих управление, так как каждый из них может содержать потенциально вредоносный код. Доверенную загрузку можно нарушить не только инъекцией DXE-драйверов, но и PEI-драйверов. Разработка драйверов PEI (как для вирусов, так и для средств защиты) сложнее, так как недоступна проинициализированная память, протоколы и системные службы. Однако, процедура инъекции PEI-драйвера в один из томов прошивки системы ничем не отличается.
Для обеспечения защиты от неконтролируемого встраивания драйверов программными средствами необходимо обеспечить гарантированное получение управления средствами защиты при каждом старте ЭВМ до запуска модулей PEI и DXE и невозможность осуществить загрузку ОС в обход средств защиты.
Гарантированное получение управления до запуска модулей можно обеспечить только в случае функционирования средства защиты на уровне PEI Core или SEC. Учитывая проприетарность кода фазы SEC, внедрение компонента защиты в PEI Core представляется правильным. Невозможность осуществить загрузку ОС в обход средств защиты можно обеспечить исключительно путем сертификации BIOS и опломбирования корпуса ЭВМ. Однако, имея сертифицированный BIOS и опломбированный корпус, можно смело утверждать, что компонент безопасности, реализованный в виде DXE-драйвера, получит управление и не позволит нарушить доверенную загрузку, проведя процедуру аутентификации и контроля целостности.
Средство защиты, которое обеспечит проверку драйверов, может быть не только программным, но и программно-аппаратным. Программная составляющая такого средства может также представлять собой DXE-драйвер, который в сочетании с аппаратно-реализованным сторожевым таймером не позволит вредоносному коду продолжить процесс загрузки в обход средства защиты. В случае, если драйвер средства защиты не получит управление через определенное время после старта системы, сторожевой таймер выполнит перезапуск системы аппаратными способами.
Итак, удалось убедиться, что вполне доступными средствами можно осуществить инъекцию вредоносного кода путем расширения BFV DXE-драйвером, более того, это было проделано на практике в стендовых условиях. В то же время эта угроза может быть сведена к нулю, если системную прошивку BIOS UEFI расширить средством защиты, которое будет перехватывать управление при старте, проводить аутентификацию и проверку целостности и в случае успеха продолжать процедуру загрузки.
Список литературы
Автор: Черчесов А. Э.
Дата публикации: 01.01.2018
Библиографическая ссылка: Черчесов А. Э. Фазы загрузки UEFI и способы контроля исполняемых образов // Вопросы защиты информации. М., 2018. № 2 (121). С. 51–53.
Когда-то давно, в начале 2014 года, я назвал состояние безопасности большинства реализаций UEFI "полумифическим". С тех пор минуло полтора года, дело осторожно двигается с мертвой точки, но до сих пор очень многие производители ПК для конечного пользователя не обращают на эту самую безопасность почти никакого внимания — «пипл хавает».
В этой статье речь пойдет о модели угроз и векторах атаки на UEFI, а также о защитах от перезаписи содержимого микросхемы BIOS — самой разрушительной по возможным последствиям атаки.
Если вам интересно, как устроена защита UEFI и какие именно уязвимости в ней так и остаются неисправленными на большинстве современных систем — добро пожаловать под кат.
Часть нулевая. Введение
Модель угроз
Прежде чем говорить о защите и уязвимостях, поговорим немного о модели угроз.
Ни одна защита не может защитить от всего сразу. К примеру, защиту прошивки от поражающего действия ядерного взрыва или от сбоев при работе в открытом космосе, я в этой статье рассматривать не буду, хотя с удовольствием почитал бы подобную статью от специалистов в соответствующей области.
Уровни доступа
Определим для атакующего несколько уровней доступа и посмотрим, что и насколько успешно «среднестатистическая» реализация UEFI может противопоставить ему:
— атакующий первого уровня имеет физический доступ к системе, способен загружать любые ОС, изменять настройки UEFI, прошивать свой код UEFI вместо оригинального на программаторе, переставлять джамперы на мат. плате, замыкать выводы микросхем и т.п.
— атакующий второго уровня имеет физический доступ к системе, но программатора у него нет.
— атакующий третьего уровня имеет удаленный доступ к системе в режиме администратора.
Остальные случаи рассматривать не будем, т.к. от более могущественного атакующего, способного менять сидящие на шарах чипы, в UEFI защищаться практически нечем, а более слабых, без прав администратора, остановит ОС.
Векторы атаки
Теперь определим основные векторы и последствия успешно совершенной атаки, в порядке уменьшения опасности:
1. Хранилище основной прошивки (в 95% современных систем — 1-2 микросхемы NOR-flash с интерфейсом SPI )
Суть атаки — вставляем свой код в прошивку, удаляем части имеющегося, воруем, убиваем, молчим про гусей.
Последствия атаки варьируются от получения полного контроля над прошивкой, аппаратурой и ОС в лучшем случае, до DoS в худшем. Физический атакующий может устроить DoS в любом случае (с размаху отверткой в плату — вот тебе и DoS), поэтому подробнее на DoS для атакующих первого и второго уровней останавливаться не буду.
2. Код в SMM
Суть — получаем доступ к особо привилегированному режиму процессора, из которого нам доступна на чтение и запись вся физическая память и много другого вкусного.
Последствия — в лучшем случае доступ к хранилищу прошивки, и далее смотри пункт 1, в худшем — обход механизмов защиты ОС и гипервизора (которые, впрочем, можно было обойти и на уровне ОС, но из SMM это может быть намного проще).
3. Хранилище прошивки PCI-устройств
Суть — вставляем свой код в прошивку какого-либо PCI-устройства (она же Option ROM), к примеру, сетевой карты или контролера Thunderbolt, UEFI выполняет этот код при инициализации устройства, . профит.
Последствия — в лучшем случае смотри пункт 1, в худшем — почти то же самое, только стартуем значительно позже, и потому некоторые вещи уже настроены и заблокированы.
4. Переменные в NVRAM
Суть — получаем возможность изменять настройки UEFI, в том числе скрытые.
Последствия — в лучшем случае можно поотключать все защиты и сразу перейти к пункту 1, в худшем — снова DoS (пишем мусор в NVRAM, перезагружаемся, смотрим, что получилось).
5. SecureBoot
Суть — получаем возможность загрузить любую нужную ОС, в том числе UEFI Shell.
Последствия — в лучшем случае получается загрузить UEFI Shell и сразу оказаться в пункте 4, в худшем — заменить стандартный загрузчик ОС на модифицированный, закрепившись таким образом в ОС, пока бдительный пользователь не включит SecureBoot обратно.
Часть первая. Защиты от записи в хранилище основной прошивки
1. Аппаратная верификация прошивки или её части перед выполнением любого кода
2. Хранилище только для чтения с аппаратным переключателем
3. PR -регистры чипсета
Если аппаратно микросхему SPI защитить от записи не получилось, можно защитить ее силами чипсета. Все современные чипсеты имеют как минимум 4 регистра PR, предназначенных для защиты от чтения и/или записи блока физической памяти, а т.к. микросхема SPI всегда отображается на «дно» первых 4 Гб физической памяти (т.е. последний байт микросхемы SPI всегда находится по физическому адресу 0xFFFFFFFF), но можно защитить всю прошивку или ее часть.
Защита подобного рода тоже не обходится без проблем:
— ее нужно правильно реализовать, не забыв, что при перезагрузке значения регистров тоже сбрасываются, и их нужно восстанавливать.
— нужно не забыть установить (и восстановить после перезагрузки) lock на их конфигурацию, иначе вредоносный код их может банально сбросить.
— защита не может быть отключена, т.е. обновление прошивки из ОС без перезагрузки становится невозможным.
— и, конечно, NVRAM и другие RW-области защитить таким способом не получится.
В отличие от предыдущего пункта, систем с PR'ами на рынке море, и почти на всех защита реализована неграмотно или неполно.
4.1. SMM_BWP и SpiRomProtect
4.2. Intel BIOS Guard, в девичестве PFAT
5. BLE и BIOS_WE
6. Отсутствующая
Хрестоматийный пример «пирожка без никто». Некоторые производители материнских плат для десктопов, не будем показывать пальцем, до сих пор не защищают прошивку от перезаписи вообще. Ваша система — вы и заморачивайтесь, никакой иллюзии безопасности мы вам не даем, только голый BIOS, только хардкор. Вести себя таким образом с каждым днем становится труднее, ведь с одной стороны давит Intel с рекомендациями, а с другой — Microsoft с HSTI , но пока справляются. Безумству храбрых, и все такое.
Заключение
С защитами от прошивки более или менее разобрались, в следующей части поговорим об SMM и атаках на него.
Буду рад любым вопросам и комментариям. Спасибо за внимание.
UEFI (Unified Extensible Firmware Interface) — замена устаревшему BIOS. Эта спецификация была придумана Intel для Itanium, тогда она еще называлась EFI (Extensible Firmware Interface), а потом была портирована на x86, x64 и ARM. Она разительно отличается от BIOS как самой процедурой загрузки, так и способами взаимодействия с ОС. Если вы купили компьютер в 2010 году и позже, то, вероятнее всего, у вас UEFI.
Основные отличия UEFI от BIOS:
Как происходит загрузка в UEFI?
С GPT-раздела с идентификатором EF00 и файловой системой FAT32, по умолчанию грузится и запускается файл \efi\boot\boot[название архитектуры].efi, например \efi\boot\bootx64.efi
Т.е. чтобы, например, создать загрузочную флешку с Windows, достаточно просто разметить флешку в GPT, создать на ней FAT32-раздел и просто-напросто скопировать все файлы с ISO-образа. Boot-секторов больше нет, забудьте про них.
Загрузка в UEFI происходит гораздо быстрее, например, загрузка моего лаптопа с ArchLinux с нажатия кнопки питания до полностью работоспособного состояния составляет всего 30 секунд. Насколько я знаю, у Windows 8 тоже очень хорошие оптимизации скорости загрузки в UEFI-режиме.
Secure Boot
«Я слышал, что Microsoft реализовывает Secure Boot в Windows 8. Эта технология не позволяет неавторизированному коду выполняться, например, бутлоадерам, чтобы защитить пользователя от malware. И есть кампания от Free Software Foundation против Secure Boot, и многие люди были против него. Если я куплю компьютер с Windows 8, смогу ли я установить Linux или другую ОС? Или эта технология позволяет запускать только Windows?»
Начнем с того, что эту технологию придумали не в Microsoft, а она входит в спецификацию UEFI 2.2. Включенный Secure Boot не означает, что вы не сможете запустить ОС, отличную от Windows. На самом деле, сертифицированные для запуска Windows 8 компьютеры и лаптопы обязаны иметь возможность отключения Secure Boot и возможность управления ключами, так что беспокоится тут не о чем. Неотключаемый Secure Boot есть только на планшетах на ARM с предустановленной Windows!
Что дает Secure Boot? Он защищает от выполнения неподписанного кода не только на этапе загрузки, но и на этапе выполнения ОС, например, как в Windows, так и в Linux проверяются подписи драйверов/модулей ядра, таким образом, вредоносный код в режиме ядра выполнить будет нельзя. Но это справедливо только, если нет физического доступа к компьютеру, т.к., в большинстве случаев, при физическом доступе ключи можно заменить на свои.
В Secure Boot есть 2 режима: Setup и User. Первый режим служит для настройки, из него вы можете заменить PK (Platform Key, по умолчанию стоит от OEM), KEK (Key Exchange Keys), db (база разрешенных ключей) и dbx (база отозванных ключей). KEK может и не быть, и все может быть подписано PK, но так никто не делает, вроде как. PK — это главный ключ, которым подписан KEK, в свою очередь ключами из KEK (их может быть несколько) подписываются db и dbx. Чтобы можно было запустить какой-то подписанный .efi-файл из-под User-режима, он должен быть подписан ключом, который в db, и не в dbx.
Для Linux есть 2 пре-загрузчика, которые поддерживают Secure Boot: Shim и PRELoader. Они похожи, но есть небольшие нюансы.
В Shim есть 3 типа ключей: Secure Boot keys (те, которые в UEFI), Shim keys (которые можно сгенерировать самому и указать при компиляции), и MOKи (Machine Owner Key, хранятся в NVRAM). Shim не использует механизм загрузки через UEFI, поэтому загрузчик, который не поддерживает Shim и ничего не знает про MOK, не сможет выполнить код (таким образом, загрузчик gummiboot не будет работать). PRELoader, напротив, встраивает свои механизмы аутентификации в UEFI, и никаких проблем нет.
Shim зависит от MOK, т.е. бинарники должны быть изменены (подписаны) перед тем, как их выполнять. PRELoader же «запоминает» правильные бинарники, вы ему сообщаете, доверяете вы им, или нет.
Оба пре-загрузчика есть в скомпилированном виде с валидной подписью от Microsoft, поэтому менять UEFI-ключи не обязательно.
Secure Boot призван защитить от буткитов, от атак типа Evil Maid, и, по моему мнению, делает это эффективно.
Спасибо за внимание!
Недавно аналитики ESET обнаружили первый в истории руткит для UEFI. Это новый и очень опасный тип вредоносных программ, который атакует компьютер до запуска Windows. В этом случае не поможет ни переустановка ОС, ни замена жесткого диска.
Ранее теоретические возможности руткитов для UEFI обсуждались только на конференциях по информационной безопасности. Сегодня киберпреступники используют их в реальных атаках.
Поэтому в новой версии ESET NOD32 для домашних пользователей мы усовершенствовали модуль «Сканер UEFI». Например, теперь пользователь может запустить «Сканер UEFI» вручную прямо в интерфейсе антивируса.
Однако большинство пользователей слабо представляют, что такое UEFI, чем он отличается от BIOS и зачем их защищать. Попробуем разобраться!
Со времени своего создания BIOS почти не развивался качественно. Выходили отдельные дополнения и расширения. Например, ACPI — усовершенствованный интерфейс управления конфигурацией и питанием (англ. Advanced Configuration and Power Interface).
Этот интерфейс упрощал установку BIOS и управление питанием, а также переходом в спящий режим. Однако этого было недостаточно, BIOS безнадежно застрял во временах MS-DOS. Например, BIOS может загружаться только с дисков объемом менее 2,1 Тб. Кроме того, у него есть проблемы с одновременной инициализацией нескольких аппаратных устройств, что приводит к замедлению загрузки на компьютерах с современными комплектующими.
В 1998 году компания Intel впервые задумалась о замене BIOS и начала работу над Extensible Firmware Interface (EFI) для недооцененной серии 64-разрядных процессоров Itanium. Для распространения нового интерфейса требовалась широкая поддержка всей отрасли. Apple выбрали EFI для Mac еще в 2006 году, но другие производители не последовали их примеру.
UEFI к нам приходит
UEFI поддерживает эмуляцию BIOS, так что у пользователей остается возможность работать на устаревших ОС остается (прим. ред. — это небезопасно!)
Новый стандарт позволяет избежать ограничений BIOS. UEFI может загружать ОС с дисков, объем которых превышает 2,2 Тб. Фактический предел для них составляет 9,4 зеттабайт . Это примерно в три раза превышает предполагаемый объем всех данных в Интернете.
UEFI поддерживает 32-битный или 64-битный режимы, а его адресное пространство больше, чем у BIOS – что значительно ускоряет загрузку. Кроме того, экран настройки UEFI обладает более гибким функционалом с поддержкой мыши и пользовательским интерфейсом.
Поддержка Secure Boot позволяет проверить, что загрузку ОС не изменила вредоносная программа. UEFI позволяет проводить удаленную настройку и отладку. BIOS так не умеет.
По сути, UEFI — самостоятельная операционная система, работающая поверх прошивки ПК. Она может храниться во флэш-памяти на материнской плате или загружаться из других источников (жесткий диск и другие носители).
Материнские платы с UEFI от разных производителей будут иметь разный интерфейс и функционал. Все зависит от конкретной модели, но базовые настройки будут одинаковыми для любого компьютера.
Как открыть настройки UEFI?
Для обычных пользователей переход от BIOS к UEFI прошел незаметно. Новый ПК будет просто быстрее загружаться при включении. Однако если вам понадобился доступ UEFI, то он будет отличаться в зависимости от операционной системы.
Windows 8
- Нажмите Win + C
- Настройки — Изменить настройки ПК
- В разделе «Настройки ПК» выберите «Общие»
- В разделе «Расширенный пуск» щелкните «Перезагрузить»
- После перезагрузки появится меню загрузки Windows 8
- В меню загрузки выберите «Поиск неисправности» — «Расширенные настройки» — «Настройка прошивки UEFI»
- Для перезагрузки системы и входа в UEFI нажмите «Перезагрузка»
Windows 10
В Win 10 в UEFI можно попытаться зайти по старинке:
- Нажмите и удерживайте кнопку питания 5 секунд
- Как только на экране появится логотип, быстро нажимайте F2 или DEL (на некоторых моделях ноутбуков клавиши могут быть другими)
Доступ из операционной системы:
- В поле поиска введите «Параметры»
- Настройки — Обновление и безопасность — Восстановление
- В разделе «Особые варианты загрузки» нажмите «Перезагрузить сейчас»
- Система перезагрузится и покажет меню загрузки Windows 10
- Устранение неполадок — Дополнительные параметры — Параметры UEFI
- Для перезагрузки системы и входа в UEFI нажмите «Перезагрузка»
Чтобы включить или отключить (чего мы делать не рекомендуем!) модуль «Сканер UEFI»:
Расширенные параметры (F5) — Модуль обнаружения — Процессы сканирования вредоносных программ
Расширенные параметры (F5) — Модуль обнаружения — Защита файловой системы в режиме реального времени
Системное программирование*,
Информационная безопасность*
Продолжаем говорить о безопасности UEFI, на этот раз речь пойдет об атаках на NVRAM и защите от них.
Неплохая, казалось бы, идея о том, что на микросхеме SPI можно хранить настройки практически вечно, не полагаясь на ненадежную и зависящую от батарейного питания CMOS SRAM, сыграла с разработчиками UEFI весьма злую шутку, теперь NVRAM с каждой новой версией стандарта обрастает все большим количеством костылей и подпорок, и конца этому процессу не видно. Если вам интересно, что именно пытаются подпереть костылем — эта статья для вас.
По традиции, всех, кто еще по каким-то причинам не читал первые три части — рекомендую начать с них, остальных с нетерпением жду под катом.
[b]Часть четвертая. NVRAM[/b]
[b]Идея на минус миллион[/b]
Честно признаться, я не знаю, кому именно в голову пришла идея переноса хранилища настроек из CMOS SRAM, где оно находилось испокон веков, на основную микросхему, но на сегодняшний момент можно констатировать, что это было той еще медвежьей услугой и производителям железа, и разработчиком прошивок, и конечным пользователям. Видимо, у Intel были на то какие-то свои причины, и потому интерфейс к NVRAM, в лице четверки Runtime-сервисов GetVariable / GetNextVariableName / QueryVariableInfo / SetVariable, стал частью самого первого опубликованного Intel (которая до организации UEFI Forum работала над ним практически единолично) стандарта EFI 1.10, прародителя всех нынешних реализаций UEFI.
[b]Как устроен NVRAM[/b]
Логически NVRAM (согласно спецификации UEFI) — это набор переменных, каждая из которых имеет GUID (не обязательно уникальный), имя (в кодировке UCS2), атрибуты (о которых ниже) и данные, которые в этой самой переменной и хранятся.
По типу переменные делятся на обычные (хранятся в RAM, при перезагрузке значений не сохраняют), NV (хранятся в выделенной для них области микросхемы SPI, при перезагрузке читаются оттуда) и HR (хранятся в микросхеме SPI, но отдельно от NV, используются ОС с поддержкой UEFI для того, чтобы сообщить прошивке об обнаруженных ошибках аппаратуры).
По уровню доступа переменные изначально делились на два типа — BS (недоступные после начала загрузки ОС) и RT (доступные всегда), но с внедрением в стандарте UEFI 2.3.1C технологии SecureBoot к обычным RT-переменным добавились еще 2 подвида — AW (для записи требуется аутентификация) и TA (то же самое, только еще с временной меткой для защиты от replay-атак).
Тип переменной определяется ее атрибутами, т.е. NV+BS+RT — хранящаяся в микросхеме SPI переменная, доступная на чтение и запись как по время загрузки, так и из ОС. Стандарт также определяет правила обращения с переменным, к примеру, наличие атрибута RT автоматически влечет наличие и BS, а запись в переменные без атрибута NV невозможна из ОС (все такие переменные становятся Read-only после возникновения события ExitBS, которым завершается работа UEFI-загрузчика).
Все было бы хорошо, если бы описанный выше интерфейс был единственным, и для доступа к переменным использовался бы только он. К сожалению, это не совсем так, и некоторыми NV-переменными практически в обход драйвера NVRAM пользуется драйвер HII, предоставляющий пользователю меню BIOS Setup, поэтому формат хранения NV-переменных тоже пришлось стандартизировать, и теперь хранить NVRAM не в микросхеме SPI, а где-то еще — довольно непросто.
Самая известная такая переменная «двойного доступа» — Setup, в которой хранятся почти 100% (за исключением паролей и еще пары вещей) настроек, доступных для изменения из BIOS Setup. Формат ее уникален для практически для каждой версии и каждой системы, но т.к. драйвер HII точно знает, по какому смещению какая настройка находится, и это знание достаточно просто извлекается при наличии образа прошивки с помощью пары утилит с открытым кодом, то это открывает атакующему некоторые потенциально опасные возможности.
[b]Атаки на NVRAM[/b]
[b]Господа забывчивые 2[/b]
Т.к. для хранения NV-переменных используется микросхема SPI, то для функционирования NVRAM необходима запись в нее во время работы ОС, что сразу ставит крест на защите при помощи RO-микросхемы или PR-регистров. Тем не менее, очень многие производители систем все равно используют PR-регистры, настраивая их таким образом, чтобы NVRAM попадал в незащищенную от записи область, но при этом умудряются начисто позабыть, что этой области требуется отдельная защита при помощи SMM-драйвера для NVRAM и установки бита SMM_BWP/SpiRomProtect. Результат забывчивости — полный доступ ко всем NV-переменным невзирая на атрибуты, в том числе к требующим аутентификации переменным SecureBoot (что сразу делает всю технологию полностью бесполезной) и к Setup (что позволяет иногда отключить и защиту остальных частей прошивки и после перезагрузки получить уже полный доступ ко всему содержимому микросхемы SPI), не говоря уже о банальном DoS. Количество уязвимых к такой нехитрой атаке систем поражает воображение, к примеру, практически все ноутбуки Acer «защищены» именно так.
Еще одни пример забывчивости — поставить для отладки RT на какую-ту важную переменную, вроде Setup, а затем забыть этот самый аттрибут убрать. Результат — можно менять настройки прямо из ОС, очень удобно, только вот опять весь SecureBoot коту под хвост.
[b]Через край[/b]
Еще одна атака, старая как мир и простая как мычание — пишем в NVRAM большие переменные, маленькие переменные, много переменных, сто раз одну и ту же переменную, и так далее и тому подобное, пушистый AFL вам в помощь. Затем перезагружаемся и смотрим на реакцию. Правильная реализация NVRAM с честью ответит на все лишние запросы EFI_OUT_OF_RESOURCES и после перезагрузки все будет работать, но не счесть примеров и иного исхода, когда NVRAM просто разваливается и система встает колом, не имея возможности продолжить загрузку. Чаще всего из этого получается DoS, но если атакующему сильно-сильно захочется — смотрите выше.
[b]UEFI-загрузчик наносит ответный удар[/b]
Эта атака тоже весьма не новая, о ней еще в 2013 году был отличный пост тов. Falseclock. Суть атаки в том, что загрузчик (в качестве которого можно использовать хоть GRUB, хоть UEFI Shell, хоть вообще любое UEFI-приложение) имеет возможность выполнить произвольный код до возникновения события ExitBS, т.е. ранние стадии загрузчика имеют полный доступ к BS-переменным, в том числе и к Setup. Если производитель платформы не позаботился о запрете записи в эту переменную после того, как временное окно для вызова BIOS Setup закончилось (я видел такую защиту ровно на одной промышленной плате, больше ее нет нигде), то загрузчик (или пользователь, если у загрузчика есть шелл) может читать и изменять содержимое переменной Setup, в пятый раз писать про опасность этого уже не стану. Предлагаемая защита от таких безобразничающих загрузчиков — SecureBoot, но с ключами по умолчанию предлагается слепо доверять Microsoft (которая клятвенно обещала IBV никогда не подписывать загрузчики с шеллом), а у тех любителей открытых ОС, у которых в прошивке по умолчанию ключи не только MS, но и Canonical, защищаться от этой атаки буквально нечем — свежайший билд GRUB2 с шеллом и прочими плюшками, подписанный ключом Canonical, можно скачать из прямо репозиториев Ubuntu.
В заключении к прошлой части я упоминал, что пароль на BIOS — от честных людей. Поясняю: защищает он, чаще всего, от несанкционированного доступа к настройкам, причем только к тем, что доступны из интерфейса BIOS Setup. При помощи подходящей утилиты для доступа к NVRAM (Read Universal), парсера UEFI-образов (UEFITool, PhoenixTool, uefi-firmware-parser) и парсера IFR (Universal IFR Extractor) можно организовать себе доступ ко всем настройкам, в том числе и скрытым, в обход пароля, а потом еще и сбросить этот самый пароль, когда через «дырку в заборе» в BIOS Setup копаться надоест.
[b]Социалисты-удалисты[/b]
Напоследок, самая безобидная NVRAM-related атака, которую может совершить на ваш ничего не подозревающий BIOS штатная Linux'овая утилита efibootmgr. В зависимости от фазы луны и интенсивности космических лучей, иногда при очередном обновлении ядра у нее получается не только добавить очередную переменную BootXXXX, но и удалить после этого несколько соседних, а если лучи в этот раз особенно высокоэнергитические — то и вообще все. После этого процентов примерно 30 реализаций UEFI авторства Phoenix или Insyde впадают в полный ступор — еще бы, фаза BDS закончилась, а загружаться больше не с чего. При этом все возможности выйти из ступора, вроде BIOS Setup, тоже были среди тех самых BootXXXX, и пользователь вынужден либо воспользоваться подсистемой Crisis Recovery (это если он может в RTFM) или нести систему в сервис. За последние пару лет лично сталкивался с этой атакой четырежды на трех принципиально разных системах. Стабильность, как говорится, признак мастерства.
[b]Лучшая защита[/b]
Может прозвучать парадоксально, но лучшая защита от всех возможных проблем с NVRAM разом — удаление из нее NV, т.е. перенос всех лежащих на микросхеме SPI переменных в RAM и установка защиты от записи в область с ними при помощи PR-регистров сразу после BIOS Setup (если делать до — настройки перестанут сохранятся). Единственная современная ОС, которая хоть как-то пользуется записью в NVRAM — MacOS X, но у них там свой лунапарк без SMM и SecureBoot, так что про них разговор отдельный. Windows и Linux великолепно переживают тот факт, что переменные NV+RT больше не сохраняются, проблемы могут быть только у инсталяторов (пишем свои загрузчики в BootXXXX, а они не сохраняются, печаль) и какого-то очень специфического софта (которому кровь из носа такие переменные нужны, но я ни разу такого софта не видел). Ни на обычную работу с ОС, ни даже на обновление прошивки (или ее отдельных компонентов) при помощи механизма Capsule Update, несохраняемая NVRAM не влияет практически никак. Поневоле задумаешься, а нужна ли она вообще была с самого начала…
[b]Заключение[/b]
Цикл понемногу подходит к концу, осталось рассказать про пару исторических атак на SecureBoot, про опасность неподписанных Option ROM'ов, и про выдающихся джентельменов (и леди), благодаря которым и была обнаружена большая часть описываемых проблем. Еще на пару частей хватит.
Спасибо читателям за внимание, удачных вам прошивок, и помните — NVRAM нужно беречь смолоду.
Читайте также: