О безопасности UEFI, часть четвертая

3b1cfb1e9a9241929a2822e25e91def5.jpg Продолжаем говорить о безопасности UEFI, на этот раз речь пойдет об атаках на NVRAM и защите от них.
Неплохая, казалось бы, идея о том, что на микросхеме SPI можно хранить настройки практически вечно, не полагаясь на ненадежную и зависящую от батарейного питания CMOS SRAM, сыграла с разработчиками UEFI весьма злую шутку, теперь NVRAM с каждой новой версией стандарта обрастает все большим количеством костылей и подпорок, и конца этому процессу не видно. Если вам интересно, что именно пытаются подпереть костылем — эта статья для вас.
По традиции, всех, кто еще по каким-то причинам не читал первыетри части — рекомендую начать с них, остальных с нетерпением жду под катом.

Часть четвертая. NVRAM


Идея на минус миллион Честно признаться, я не знаю, кому именно в голову пришла идея переноса хранилища настроек из CMOS SRAM, где оно находилось испокон веков, на основную микросхему, но на сегодняшний момент можно констатировать, что это было той еще медвежьей услугой и производителям железа, и разработчиком прошивок, и конечным пользователям. Видимо, у Intel были на то какие-то свои причины, и потому интерфейс к NVRAM, в лице четверки Runtime-сервисов GetVariable / GetNextVariableName / QueryVariableInfo / SetVariable, стал частью самого первого опубликованного Intel (которая до организации UEFI Forum работала над ним практически единолично) стандарта EFI 1.10, прародителя всех нынешних реализаций UEFI.Как устроен NVRAM Логически 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 точно знает, по какому смещению какая настройка находится, и это знание достаточно просто извлекается при наличии образа прошивки с помощью пары утилит с открытым кодом, то это открывает атакующему некоторые потенциально опасные возможности.Атаки на NVRAM Господа забывчивые 2 Т.к. для хранения NV-переменных используется микросхема SPI, то для функционирования NVRAM необходима запись в нее во время работы ОС, что сразу ставит крест на защите при помощи RO-микросхемы или PR-регистров. Тем не менее, очень многие производители систем все равно используют PR-регистры, настраивая их таким образом, чтобы NVRAM попадал в незащищенную от записи область, но при этом умудряются начисто позабыть, что этой области требуется отдельная защита при помощи SMM-драйвера для NVRAM и установки бита SMM_BWP/SpiRomProtect. Результат забывчивости — полный доступ ко всем NV-переменным невзирая на атрибуты, в том числе к требующим аутентификации переменным SecureBoot (что сразу делает всю технологию полностью бесполезной) и к Setup (что позволяет иногда отключить и защиту остальных частей прошивки и после перезагрузки получить уже полный доступ ко всему содержимому микросхемы SPI), не говоря уже о банальном DoS. Количество уязвимых к такой нехитрой атаке систем поражает воображение, к примеру, практически все ноутбуки Acer «защищены» именно так.
Еще одни пример забывчивости — поставить для отладки RT на какую-ту важную переменную, вроде Setup, а затем забыть этот самый аттрибут убрать. Результат — можно менять настройки прямо из ОС, очень удобно, только вот опять весь SecureBoot коту под хвост.Через край Еще одна атака, старая как мир и простая как мычание — пишем в NVRAM большие переменные, маленькие переменные, много переменных, сто раз одну и ту же переменную, и так далее и тому подобное, пушистый AFL вам в помощь. Затем перезагружаемся и смотрим на реакцию. Правильная реализация NVRAM с честью ответит на все лишние запросы EFI_OUT_OF_RESOURCES и после перезагрузки все будет работать, но не счесть примеров и иного исхода, когда NVRAM просто разваливается и система встает колом, не имея возможности продолжить загрузку. Чаще всего из этого получается DoS, но если атакующему сильно-сильно захочется — смотрите выше.UEFI-загрузчик наносит ответный удар Эта атака тоже весьма не новая, о ней еще в 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 копаться надоест.Социалисты-удалисты Напоследок, самая безобидная NVRAM-related атака, которую может совершить на ваш ничего не подозревающий BIOS штатная Linux'овая утилита efibootmgr. В зависимости от фазы луны и интенсивности космических лучей, иногда при очередном обновлении ядра у нее получается не только добавить очередную переменную BootXXXX, но и удалить после этого несколько соседних, а если лучи в этот раз особенно высокоэнергитические — то и вообще все. После этого процентов примерно 30 реализаций UEFI авторства Phoenix или Insyde впадают в полный ступор — еще бы, фаза BDS закончилась, а загружаться больше не с чего. При этом все возможности выйти из ступора, вроде BIOS Setup, тоже были среди тех самых BootXXXX, и пользователь вынужден либо воспользоваться подсистемой Crisis Recovery (это если он может в RTFM) или нести систему в сервис. За последние пару лет лично сталкивался с этой атакой четырежды на трех принципиально разных системах. Стабильность, как говорится, признак мастерства.Лучшая защита Может прозвучать парадоксально, но лучшая защита от всех возможных проблем с NVRAM разом — удаление из нее NV, т.е. перенос всех лежащих на микросхеме SPI переменных в RAM и установка защиты от записи в область с ними при помощи PR-регистров сразу после BIOS Setup (если делать до — настройки перестанут сохранятся). Единственная современная ОС, которая хоть как-то пользуется записью в NVRAM — MacOS X, но у них там свой лунапарк без SMM и SecureBoot, так что про них разговор отдельный. Windows и Linux великолепно переживают тот факт, что переменные NV+RT больше не сохраняются, проблемы могут быть только у инсталяторов (пишем свои загрузчики в BootXXXX, а они не сохраняются, печаль) и какого-то очень специфического софта (которому кровь из носа такие переменные нужны, но я ни разу такого софта не видел). Ни на обычную работу с ОС, ни даже на обновление прошивки (или ее отдельных компонентов) при помощи механизма Capsule Update, несохраняемая NVRAM не влияет практически никак. Поневоле задумаешься, а нужна ли она вообще была с самого начала…

Заключение


Цикл понемногу подходит к концу, осталось рассказать про пару исторических атак на SecureBoot, про опасность неподписанных Option ROM'ов, и про выдающихся джентельменов (и леди), благодаря которым и была обнаружена большая часть описываемых проблем. Еще на пару частей хватит.
Спасибо читателям за внимание, удачных вам прошивок, и помните — NVRAM нужно беречь смолоду.

© Habrahabr.ru