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

    Продолжаем говорить о безопасности 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 нужно беречь смолоду.
    Поделиться публикацией

    Похожие публикации

    Комментарии 13

      +1
      > про выдающихся джентельменов (и леди), благодаря которым и была обнаружена большая часть описываемых проблем
      Рафаль да Рутковска ;) Ну и интеловская security-команда.

      Меня на самом деле удивляет что большинство атак являются vendor-nonspecific. Если не ставят D_LOCK (привет 2006!), то не ставит никто. Если есть проблемы с S3 resume script, то сразу у всех.
      А вот косяков реализации конкретных ведоров (всякие buffer overflow, нарушения логики SMI-обработчиков) не слышно. Не исследуют? Или просто вендоров и реализаций куча?
        +1
        LegbaCore еще.

        Исследуют, но такие косяки обычно исправляют молча, т.к. IBV не дают разрешение на публикацию деталей уязвимости. Самое смешное, что скрываться в данном случае не только вредно со всех точек зрения, кроме маркетинговой, но и совершенно бессмысленно — о том, что какая-то уязвимость исправлена, можно узнать банально исследуя разницу между двумя версиями прошивки. Причем делать это можно не только вручную, но и автоматически, благодаря проекту Тедди Рида Subzero.io.
          +1
          А вот косяков реализации конкретных ведоров (всякие buffer overflow, нарушения логики SMI-обработчиков) не слышно.

          Дофига и больше, просто эксплойты которые будут работать на паре конкретных моделей конкретных вендоров — это не очень интересно с практической точки зрения.
          +2
          Верните старый добрый механический джампер…
          Это же так просто… но нет, иначе просто масса народа останется без работы.
            0
            Не вернут, и дело точно не в работе, скорее в том, что решения. принятые более 10 лет назад, изменить будет не так просто. Кто о безопасности NVRAM уже задумался — у тех есть и его резервное копирование, и защита от разрушения, и восстановлние после сбоя, и возможность преноса в отдельную микросхему, но массовому рынку это все просто не нужно — «работает, и слава Богу».
              0
              Массово посыпятся вирусы которые используют эти уязвимости и защита сразу станет нужна всем…
                0
                10 лет прошло, а про массовые вирусы в SMM и гипервизоре не слышно.
                  +2
                  может вирусы просто не массовые, а сугубо заказные ;) Сделал свое черное дело, и все…
                    0
                    Пока есть более простые способы распространения, сдвигов не будет.
                    +3
                    Появятся, конечно, рано или поздно, так или иначе.
                    Но на данный момент "юзерленд по прежнему в полной Ж", а разработка вирусов для Windows стоит дешевле и окупается быстрее, чем разработка руткитов для UEFI.
                    Главное, что о безопасности задумались вообще, а то ведь 10 лет до этого сидели с открытой на запись микросхемой и не парились совсем, а теперь вот то одну уязвимость закроют, то другую.
                +1
                парни в Insyde слегка перестарались с защитой, имею девайс с их UEFI без legacy CSM, так вот, новый BootXXXX для внутреннего eMMC можно добавить только если он имеет boot file "/EFI/Microsoft/Boot/bootmgr.efi", никакие другие не сохраняются после перезагрузки. Просто происходит дроп всех BootXXXX, которые не bootmgr.efi или usb-hdd, usb-cdrom.

                ковырялся пару дней, попробовал все варианты разбития eMMC, в итоге пришлось вкорячить прикидывающийся «Windows Boot Manager» rEFInd.
                • НЛО прилетело и опубликовало эту надпись здесь
                    0
                    Не где-то там а в CMOS — единственном месте где старый BIOS может хранить свои настройки. Доступ туда осуществлялся через 70 и 71 порт, конструкция была очень простой.
                    В принципе и на современных виндовс можно получить туда доступ установив специальный драйвер который популярен у радиолюбителей (проброс портов в UserSpace). Но всё осложняется тем что доступ не атомарный, в любой момент другой процесс может помешать работе вашего приложения. Виндовс довольно активно обращается туда чтобы считать время, поэтому с большой степенью вероятности попытка попортить настройки записью одного байта приведет только к порче времени, которое не находится под защитой контрольной суммы. Нужно активно писать туда чтобы быть уверенным в успехе.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое