Оригинал
В октябре 2022 года в Интернете появилась утечка исходного кода BIOS для процессоров Intel Alder Lake. Утечка кода состояла из компонентов прошивки, которые были получены из трех источников:
Независимый поставщик BIOS (IBV) под названием Insyde Software,
Собственный код BIOS Alder Lake, разработанный Intel,
реализация UEFI с открытым исходным кодом Tianocore EDK2.
Я получил копию просочившегося кода и начал поиск уязвимостей. Эта статья посвящена уязвимостям, которые я нашел и о которых сообщил компании Insyde Software. Эти ошибки охватывают различные модули режима управления системой (SMM), включая:
диспетчер Insyde H2O Internal Soft-SMI Interface (IHISI)
обработчики Flash BIOS Through SMI (FTBS)
обработчики BIOS Guard SMI
Что такое режим управления системой и почему он интересен?
Прежде чем погрузиться в детали ошибки, давайте сначала сделаем небольшой экскурс и поговорим о режиме управления системой. SMM - это высокопривилегированный режим работы x86. Он имеет различные цели, включая управление аппаратным обеспечением и периферийными устройствами, обработку аппаратных прерываний, управление питанием и многое другое. SMM иногда называют " Ring -2", используя номенклатуру колец защиты.
ЦП переходит в режим управления системой, когда выдается прерывание управления системой (SMI). SMI может быть сгенерировано аппаратно или программно, например, при записи в порт ввода-вывода. Эти прерывания имеют высокий приоритет и являются немаскируемыми (например, их нельзя игнорировать).
SMM выполняется из защищенной области памяти, известной как System Management RAM (SMRAM). Регистр System-Management Range Register (SMRR) может быть (*кхм* должен быть) запрограммирован для ограничения доступа к области SMRAM, предотвращая доступ внешних агентов к SMRAM. Другими словами, ОС не должна иметь возможности читать или писать SMRAM, чтобы напрямую влиять на выполнение SMM.
Выполнение SMM происходит незаметно для операционной системы. Пока выполняется обработчик SMI, так называемая процедура SMI Rendezvous заставит другие ядра процессора также подключиться к SMM и ждать. ОС не может видеть или проверять, что делает SMM. Но с другой стороны, SMM может влиять на выполнение ОС. SMM имеет (почти) полный доступ к DRAM платформы. Я говорю "почти", потому что есть несколько исключений, например, определенные участки DRAM, которые принадлежат еще более высокопривилегированным микропрограммным ИС, таким как PSP от AMD или CSME от Intel. Помимо практически полного доступа к физической памяти, SMM обладает дополнительными мощными возможностями: Он имеет полный доступ к SPI флеш-памяти платформы и может читать/писать все MSR. По этим причинам SMM является желательным местом для внедрения буткита злоумышленниками. Такой буткит будет одновременно невидим для большинства антивирусных программ, а также будет обладать высокими привилегиями. Если вы хотите прочитать больше по теме буткитов, Алекс Матросов проделал отличную работу по документированию некоторых примеров. Вам также может быть интересно ознакомиться с проектом SmmBackdoor.
Одним из наиболее важных требований безопасности для предотвращения эксплуатации SMM во время выполнения является сохранение целостности SMRAM. Другими словами: Просто не допускайте повреждения памяти. Но, как мы знаем, это непростая задача, особенно потому, что прошивка SMM написана на языке C, где неопределенное поведение имеет огромный размах, а обеспечение безопасности памяти сродни тонкому цирковому номеру с балансированием на нескольких вращающихся тарелках.
Поэтому неудивительно, что за прошедшие годы было найдено бесчисленное количество примеров уязвимостей повреждения памяти в SMM. Для дальнейшего чтения я рекомендую вам ознакомиться с каталогом Xeno Kovah "Low Level PC/Server Attacks", в котором представлена впечатляющая хронология исследований уязвимостей SMM (среди прочих интересных тем по безопасности встроенного ПО!).
Области атак SMM
В SMM отдельные обработчики SMI регистрируются с помощью функции gSmst->SmiHandlerRegister(). Каждый обработчик имеет уникальный GUID, который используется для выбора соответствующего обработчика, когда ОС вызывает SMI.
Аргументы могут быть переданы обработчикам SMI через коммуникационный буфер в общей памяти. Строгая проверка ввода всех аргументов, передаваемых обработчику SMI, имеет первостепенное значение для сохранения свойства безопасности памяти.
Другая поверхность атаки связана с различными ресурсами платформы, которые совместно используются SMM и другими агентами, такими как ОС хоста, периферийные устройства и микропрограммные IP. Здесь условия гонки, такие как проблемы времени проверки и времени использования (TOCTOU), также представляют значительную проблему. Некоторые типичные примеры общих ресурсов, потребляемых SMM, включают следующее:
SPI флэш-память (например, переменные EFI)
ввод-вывод с привязкой к памяти (например, PCIe BARs)
Общие области физической памяти (например, буфер SMI Comm Buffer)
Регистры, специфичные для модели (MSR).
Поскольку эти ресурсы могут совместно использоваться несколькими агентами с различными уровнями привилегий, вредоносный агент с низкими привилегиями может вмешаться в общие данные, пока SMM обрабатывает их.
Еще один класс уязвимостей в SMM - наложение и замещение. Проблемы могут возникнуть, когда злоумышленник передает SMM аргумент указателя (например, Comm Buffer), но заставляет буфер наложиться на SMRAM. Если обработчик SMI не сможет проверить указатель (не забывайте и о вложенных указателях!), он может ошибочно читать или записывать свое собственное адресное пространство, полагая, что читает вход SMI или записывает выход SMI. Это, конечно, приведет к нежелательному результату - повреждению SMRAM.
Если вы хотите узнать больше по этим темам, ознакомьтесь с техническим документом “A Tour Beyond BIOS: SMM Communication” в котором содержится подробное описание этих и других классов уязвимостей, относящихся к SMM.
Наконец, я хочу добавить, что инициатива Microsoft’s “Secured-Core PC” начинает подталкивать отрасль к усилению контроля SMM за счет использования SMM-супервизора, который эффективно лишает прав и изолирует обработчиков SMI. Хотя, как и большинство защитных технологий, творческие люди найдут способы сломать ее. Например, в прошлом году Илья ван Шпрундель из IOActive представил отличное исследование, которое выявило несколько критических уязвимостей в программе Microsoft MM Supervisor, которая является частью Project Mu.
В центре моего исследования
Обработчики SMI обычно получают входные аргументы через коммуникационный буфер, который находится в области разделяемой памяти, которая может быть определена статически или динамически. Как упоминалось выше, буфер связи должен располагаться вне SMRAM, и в обязанности SMM входит принудительное выполнение этого требования при каждой обработке SMI.
Однако обработчики SMI могут также получать аргументы через регистры общего назначения. Итак, как же это работает? Что ж, когда ОС выдает SMI, состояние процессора сохраняется, а контекст выполнения переключается на SMM. Сохраненные регистры общего назначения находятся внутри SMRAM в области сохранения состояния. Все это необходимо, потому что, когда обработчик SMI завершается, состояние процессора должно быть восстановлено, чтобы управление выполнением могло быть возвращено вызывающей стороне.
Конечно, вредоносная или скомпрометированная ОС хоста может поместить любые значения в эти регистры до вызова SMI. Согласно модели угроз SMM, ОС полностью ненадежна, поэтому обработчики SMI должны быть предельно осторожны при проверке всех данных, считываемых из области сохранения состояния.
Для своего исследования я сосредоточился на UEFI BIOS Insyde H2O (аппаратно--операционная система), который предоставляет интерфейс SMI под названием IHISI (внутренний программно-SMI интерфейс Insyde H2O). Этот интерфейс состоит из множества подкоманд, которые считывают и записывают эти сохраненные регистры состояний, обрабатывая их как аргументы для обработчиков подкоманд.
Давайте углубимся в детали ошибки!
Сведения об уязвимости
Все эти уязвимости имеют общую первопричину (недостаточная проверка вводимых данных) и общее воздействие (повреждение SMRAM). Их подробная информация приведена в следующей таблице:
Эти проблемы были исправлены в выпуске Insyde, который вышел 10 апреля 2023 года. Они затрагивают несколько различных платформ Insyde, охватывающих мобильные и серверные устройства Intel и AMD. Конкретные платформы и версии можно найти в рекомендациях Insyde, ссылки на которые приведены выше.
Ошибка 1. IhisiServicesSmm: Сохранить State Register государственный реестр, не проверенный перед использованием
Следующий обработчик SMI является подфункцией IHISI, которая связана с Flash BIOS Insyde через функциональность SMI (FTBS). Обработчик считывает указатель структуры с именем BiosRomMap из RDI в области сохранения состояния.
Этот указатель не проверяется до разыменования как для операций чтения, так и для операций записи. Уязвимость наложения возникает, когда вызывающий абонент заставляет RDI указывать на SMRAM. Это эффективно вынуждает SMM ошибочно обращаться к своему собственному частному пространству памяти.
Затем выполняется обход массива BiosRomMap для подсчета количества областей, что влияет на условие контроля цикла for, потенциально позволяя Indxe (sic) накапливаться до большого целочисленного значения. В совокупности эти отсутствующие проблемы с проверкой входных данных могут позволить злоумышленнику повредить SMRAM в приведенных ниже строках:
Наконец, перед возвратом сохраненный регистр RDI используется для копирования обновленного BiosRomMapобратно вызывающему объекту, вызвавшему обработчик SMI.
Но еще раз, поскольку RDI ранее не проверялся для предотвращения дублирования с SMRAM, CopyMem может перезаписать SMRAM.
Ошибка 2. IhisiServicesSmm: повреждение памяти в обработчике FTBS SMI
Insyde IHISI предоставляет подкоманду (AH=0x48), которая обрабатывается следующей функцией.
Обработчик SMI получает входные данные, контролируемые злоумышленником, через регистр сохранения состояния RSI. Ниже, ImageBlkPtrиспорчен вызывающей стороной и разыменовывается без проверки того, не перекрывает ли он SMRAM. Кроме того, вложенный указатель, ImageBlock, также разыменовывается без проверки перекрытия SMRAM.
Затем, наконец, проверяется внутренний указатель с именем ImageBase, чтобы убедиться, что он не перекрывает SMRAM. Но при проверке на перекрытие вызов hisiProtBufferInCmdBuffer() использует значение ImageBlock->ImageBlockSize, которое также контролируется злоумышленником. Это эффективно позволяет легко обойти проверку работоспособности.
Позже в обработчике SMI вызывается функция MergeImageBlockWithoutCompress(). Эта функция также считывает регистр этапа сохранения RSI, чтобы получить указатель ImageBlkPtr. На этот раз функция действительно проверяет, перекрывает ли указатель SMRAM, но делает это только после разыменования его. Этот шаблон разыменования с последующей проверкой, скорее всего, является всего лишь неинтересным отказом в обслуживании.
Однако, что более интересно, так это использование указателя ImageBlock, потому что из предыдущего анализа мы знаем, что этот указатель контролируется злоумышленником. Если он указывает на память, контролируемую злоумышленником, он подвержен уязвимостям TOCTOU. В результате ImageBlock->ImageBlockSize может изменяться между несколькими разыменованиями, показанными ниже.
Если злоумышленник, способный к DMA, выигрывает это условие гонки, он может изменить ImageBlock->ImageBlockSize после того, как он был проверен, но до того, как он будет использован в вызове CopyMem(). Это приводит к повреждению памяти за пределами конечной области памяти назначения. Любопытно, что указатель назначения изначально был получен из переменной EFI “SecureFlashInfo” (не показана для краткости), которая хранится с атрибутами BS+RT+NV, что указывает на то, что ее значение также контролируется вредоносной ОС хоста. В заключение, это означает, что злоумышленник контролирует адрес назначения, адрес источника и параметры размера, которые передаются в CopyMem(). Это мощный примитив повреждения памяти "write-what-where"
Ошибка 3. IhisiServicesSmm: Выполнение подфункции IHISI может привести к повреждению SMRAM
Следующий блок кода показывает диспетчер основной подфункции IHISI. Он просматривает таблицу подфункций, находит зарегистрированную подфункцию, которая соответствует коду команды, а затем вызывает функцию обработчика, как показано ниже:
После возврата подфункции, и если CmdCode равен OEMSFOEMExCommunication, содержимое буфера будет скопировано обратно вызывающей стороне в качестве выходных данных SMI. Адрес назначения для этой операции CopyMem() определяется вызывающей стороной обработчика SMI, поскольку он был передан в регистре состояния сохранения RCX.
Проблема здесь в том, что когда злоумышленник контролирует содержимое RCX, он может заставить приведенный выше код записать mApCommDataBuffer в контролируемое злоумышленником местоположение в SMRAM.
Оценивая влияние этого, мы должны проверить, правильно ли каждая подфункция IHISI проверяет RCX, прежде чем возвращаться к диспетчеру. Соответствующие подфункции, связанные с кодом команды OEMSFOEMExCommunication, перечислены ниже:
После тщательной проверки мы определили, что большинство из этих подфункций IHISI выполняют строгую проверку указателя, хранящегося в RCX. Например, ниже показан первый обработчик, KernelCommunicationSaveRegs(). Здесь мы можем наблюдать, что ApCommDataBuffer (указатель, который был считан из RCX) проверяется, чтобы убедиться, что он правильно находится внутри буфера связи.
Однако есть две подфункции, которые не проверяют RCX:
KernelT51EcIdelTrue()
KernelT51EcIdelFalse()
Эта оплошность, скорее всего, является следствием того факта, что эти подфункции не используют RCX, поэтому, возможно, разработчик предположил, что нет необходимости проверять RCX. Однако, несмотря на то, что эти подфункции никогда не используют RCX, диспетчер IhisiProtExecuteCommandByPriority() все равно будет использовать RCX в качестве адреса назначения для операции CopyMem(). Следовательно, если злоумышленник установит адрес в RCX, который перекрывает SMRAM, перед вызовом подфункций S41Kn_T51EcIdelTrue или S41Kn_T51EcIdelFalse, они могут повредить SMRAM содержимым буфера связи AP.
Ошибка 4. IhisiServicesSmm: Запись на адрес, контролируемый злоумышленником
Следующий обработчик SMI считывает указатель структуры с именем Output Data из регистра состояния сохранения RCX, как показано ниже:
Затем обработчик SMI выполняет запись в поля этой структуры без проверки. OutputDataдля перекрытия с SMRAM.
Рискую показаться заезженной пластинкой: еще раз повторю, что это простая уязвимость, связанная с повреждением памяти SMM.
Ошибка 5. ChipsetSvcSmm: Недостаточная проверка ввода в обновлениях BIOS Guard
BIOS Guard - это функция безопасности, входящая в маркетинговую программу Intel “Hardware Shield”. Это усложняет процесс обновления BIOS flash, ограничивая доступ к SPI flash через BIOS Guard ACM, который проверяет подлинность обновлений BIOS. Существует мало общедоступной документации по BIOS Guard, но в этом докладе раскрываются некоторые аспекты дизайна, которые Алекс восстановил с помощью обратного инжиниринга. Следующая уязвимость затрагивает SMM-модуль Insyde, который анализирует заголовок обновления BIOS Guard, расположение которого показано ниже:
Ниже InputDataBuffer считывается из RSI и указывает на приведенную выше структуру обновления BIOS Guard. Этот указатель разыменовывается для вычисления смещения сертификата BIOS Guard (BgupcOffset) без предварительной проверки того, перекрывает ли указатель SMRAM. Поскольку ScriptSectionSize и DataSectionSize (оба типа UINT32) повреждены, BgupcOffset также следует считать поврежденным и может принимать любое 32-разрядное целочисленное значение.
Затем из RDI считывается значение bufferSize, и оно используется для проверки того, находится ли входной буфер внутри командного буфера. Однако в этом коде отсутствуют строгие проверки, гарантирующие, что размер буфера достаточно велик. Если размер буфера оказался меньше размера структуры BGUP_HEADER, то более ранние разыменования указателя (при чтении элементов из BgupHeader) могли бы получить доступ к памяти за пределами входного буфера, что привело бы к чтению вне границ.
Затем проверяется BgupcSize, чтобы убедиться, что он соответствует размеру буфера. Однако эту проверку работоспособности также можно обойти, поскольку злоумышленник контролирует обе части условного выражения — как BgupcOffset, так и bufferSize.
Последним шагом, выполняемым перед запуском BIOS Guard ACM, является использование управляемого злоумышленником BgupcOffset (который может быть очень большим) для копирования сертификата и обновления данных. Это показано ниже:
Приведенные выше вызовы CopyMem() могут привести к повреждению SMRAM, когда перезаписывается память за пределами области mBiosGuardMemAddress.
В октябре 2022 года в Интернете появилась утечка исходного кода BIOS для процессоров Intel Alder Lake. Утечка кода состояла из компонентов прошивки, которые были получены из трех источников:
Независимый поставщик BIOS (IBV) под названием Insyde Software,
Собственный код BIOS Alder Lake, разработанный Intel,
реализация UEFI с открытым исходным кодом Tianocore EDK2.
Я получил копию просочившегося кода и начал поиск уязвимостей. Эта статья посвящена уязвимостям, которые я нашел и о которых сообщил компании Insyde Software. Эти ошибки охватывают различные модули режима управления системой (SMM), включая:
диспетчер Insyde H2O Internal Soft-SMI Interface (IHISI)
обработчики Flash BIOS Through SMI (FTBS)
обработчики BIOS Guard SMI
Что такое режим управления системой и почему он интересен?
Прежде чем погрузиться в детали ошибки, давайте сначала сделаем небольшой экскурс и поговорим о режиме управления системой. SMM - это высокопривилегированный режим работы x86. Он имеет различные цели, включая управление аппаратным обеспечением и периферийными устройствами, обработку аппаратных прерываний, управление питанием и многое другое. SMM иногда называют " Ring -2", используя номенклатуру колец защиты.
ЦП переходит в режим управления системой, когда выдается прерывание управления системой (SMI). SMI может быть сгенерировано аппаратно или программно, например, при записи в порт ввода-вывода. Эти прерывания имеют высокий приоритет и являются немаскируемыми (например, их нельзя игнорировать).
SMM выполняется из защищенной области памяти, известной как System Management RAM (SMRAM). Регистр System-Management Range Register (SMRR) может быть (*кхм* должен быть) запрограммирован для ограничения доступа к области SMRAM, предотвращая доступ внешних агентов к SMRAM. Другими словами, ОС не должна иметь возможности читать или писать SMRAM, чтобы напрямую влиять на выполнение SMM.
Выполнение SMM происходит незаметно для операционной системы. Пока выполняется обработчик SMI, так называемая процедура SMI Rendezvous заставит другие ядра процессора также подключиться к SMM и ждать. ОС не может видеть или проверять, что делает SMM. Но с другой стороны, SMM может влиять на выполнение ОС. SMM имеет (почти) полный доступ к DRAM платформы. Я говорю "почти", потому что есть несколько исключений, например, определенные участки DRAM, которые принадлежат еще более высокопривилегированным микропрограммным ИС, таким как PSP от AMD или CSME от Intel. Помимо практически полного доступа к физической памяти, SMM обладает дополнительными мощными возможностями: Он имеет полный доступ к SPI флеш-памяти платформы и может читать/писать все MSR. По этим причинам SMM является желательным местом для внедрения буткита злоумышленниками. Такой буткит будет одновременно невидим для большинства антивирусных программ, а также будет обладать высокими привилегиями. Если вы хотите прочитать больше по теме буткитов, Алекс Матросов проделал отличную работу по документированию некоторых примеров. Вам также может быть интересно ознакомиться с проектом SmmBackdoor.
Одним из наиболее важных требований безопасности для предотвращения эксплуатации SMM во время выполнения является сохранение целостности SMRAM. Другими словами: Просто не допускайте повреждения памяти. Но, как мы знаем, это непростая задача, особенно потому, что прошивка SMM написана на языке C, где неопределенное поведение имеет огромный размах, а обеспечение безопасности памяти сродни тонкому цирковому номеру с балансированием на нескольких вращающихся тарелках.
Поэтому неудивительно, что за прошедшие годы было найдено бесчисленное количество примеров уязвимостей повреждения памяти в SMM. Для дальнейшего чтения я рекомендую вам ознакомиться с каталогом Xeno Kovah "Low Level PC/Server Attacks", в котором представлена впечатляющая хронология исследований уязвимостей SMM (среди прочих интересных тем по безопасности встроенного ПО!).
Области атак SMM
В SMM отдельные обработчики SMI регистрируются с помощью функции gSmst->SmiHandlerRegister(). Каждый обработчик имеет уникальный GUID, который используется для выбора соответствующего обработчика, когда ОС вызывает SMI.
Аргументы могут быть переданы обработчикам SMI через коммуникационный буфер в общей памяти. Строгая проверка ввода всех аргументов, передаваемых обработчику SMI, имеет первостепенное значение для сохранения свойства безопасности памяти.
Другая поверхность атаки связана с различными ресурсами платформы, которые совместно используются SMM и другими агентами, такими как ОС хоста, периферийные устройства и микропрограммные IP. Здесь условия гонки, такие как проблемы времени проверки и времени использования (TOCTOU), также представляют значительную проблему. Некоторые типичные примеры общих ресурсов, потребляемых SMM, включают следующее:
SPI флэш-память (например, переменные EFI)
ввод-вывод с привязкой к памяти (например, PCIe BARs)
Общие области физической памяти (например, буфер SMI Comm Buffer)
Регистры, специфичные для модели (MSR).
Поскольку эти ресурсы могут совместно использоваться несколькими агентами с различными уровнями привилегий, вредоносный агент с низкими привилегиями может вмешаться в общие данные, пока SMM обрабатывает их.
Еще один класс уязвимостей в SMM - наложение и замещение. Проблемы могут возникнуть, когда злоумышленник передает SMM аргумент указателя (например, Comm Buffer), но заставляет буфер наложиться на SMRAM. Если обработчик SMI не сможет проверить указатель (не забывайте и о вложенных указателях!), он может ошибочно читать или записывать свое собственное адресное пространство, полагая, что читает вход SMI или записывает выход SMI. Это, конечно, приведет к нежелательному результату - повреждению SMRAM.
Если вы хотите узнать больше по этим темам, ознакомьтесь с техническим документом “A Tour Beyond BIOS: SMM Communication” в котором содержится подробное описание этих и других классов уязвимостей, относящихся к SMM.
Наконец, я хочу добавить, что инициатива Microsoft’s “Secured-Core PC” начинает подталкивать отрасль к усилению контроля SMM за счет использования SMM-супервизора, который эффективно лишает прав и изолирует обработчиков SMI. Хотя, как и большинство защитных технологий, творческие люди найдут способы сломать ее. Например, в прошлом году Илья ван Шпрундель из IOActive представил отличное исследование, которое выявило несколько критических уязвимостей в программе Microsoft MM Supervisor, которая является частью Project Mu.
В центре моего исследования
Обработчики SMI обычно получают входные аргументы через коммуникационный буфер, который находится в области разделяемой памяти, которая может быть определена статически или динамически. Как упоминалось выше, буфер связи должен располагаться вне SMRAM, и в обязанности SMM входит принудительное выполнение этого требования при каждой обработке SMI.
Однако обработчики SMI могут также получать аргументы через регистры общего назначения. Итак, как же это работает? Что ж, когда ОС выдает SMI, состояние процессора сохраняется, а контекст выполнения переключается на SMM. Сохраненные регистры общего назначения находятся внутри SMRAM в области сохранения состояния. Все это необходимо, потому что, когда обработчик SMI завершается, состояние процессора должно быть восстановлено, чтобы управление выполнением могло быть возвращено вызывающей стороне.
Конечно, вредоносная или скомпрометированная ОС хоста может поместить любые значения в эти регистры до вызова SMI. Согласно модели угроз SMM, ОС полностью ненадежна, поэтому обработчики SMI должны быть предельно осторожны при проверке всех данных, считываемых из области сохранения состояния.
Для своего исследования я сосредоточился на UEFI BIOS Insyde H2O (аппаратно--операционная система), который предоставляет интерфейс SMI под названием IHISI (внутренний программно-SMI интерфейс Insyde H2O). Этот интерфейс состоит из множества подкоманд, которые считывают и записывают эти сохраненные регистры состояний, обрабатывая их как аргументы для обработчиков подкоманд.
Давайте углубимся в детали ошибки!
Сведения об уязвимости
Все эти уязвимости имеют общую первопричину (недостаточная проверка вводимых данных) и общее воздействие (повреждение SMRAM). Их подробная информация приведена в следующей таблице:
| # | Title | CVE | Insyde | CVSS |
| 1 | IhisiServicesSmm: Save State Register Not Checked Before Use | CVE-2023-22616 | SA-2023022 | 6.4 |
| 2 | IhisiServicesSmm: Memory Corruption in FTBS SMI Handler | CVE-2023-22612 | SA-2023019 | 8.1 |
| 3 | IhisiServicesSmm: IHISI Subfunction Execution May Corrupt SMRAM. | CVE-2023-22615 | SA-2023021 | 6.4 |
| 4 | IhisiServicesSmm: Write To Attacker Controlled Address | CVE-2023-22613 | SA-2023023 | 7.3 |
| 5 | ChipsetSvcSmm: Insufficient Input Validation In BIOS Guard Updates | CVE-2023-22614 | SA-2023020 | 7.9 |
Эти проблемы были исправлены в выпуске Insyde, который вышел 10 апреля 2023 года. Они затрагивают несколько различных платформ Insyde, охватывающих мобильные и серверные устройства Intel и AMD. Конкретные платформы и версии можно найти в рекомендациях Insyde, ссылки на которые приведены выше.
Ошибка 1. IhisiServicesSmm: Сохранить State Register государственный реестр, не проверенный перед использованием
Следующий обработчик SMI является подфункцией IHISI, которая связана с Flash BIOS Insyde через функциональность SMI (FTBS). Обработчик считывает указатель структуры с именем BiosRomMap из RDI в области сохранения состояния.
Код:
EFI_STATUS EFIAPI FbtsGetWholeBiosRomMap ( VOID )
{
UINTN RomMapSize;
UINTN NumberOfRegions;
FBTS_INTERNAL_BIOS_ROM_MAP *BiosRomMap;
UINTN Indxe;
NumberOfRegions = 0;
BiosRomMap = (FBTS_INTERNAL_BIOS_ROM_MAP *) (UINTN)
mH2OIhisi->ReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI);
...
Этот указатель не проверяется до разыменования как для операций чтения, так и для операций записи. Уязвимость наложения возникает, когда вызывающий абонент заставляет RDI указывать на SMRAM. Это эффективно вынуждает SMM ошибочно обращаться к своему собственному частному пространству памяти.
Затем выполняется обход массива BiosRomMap для подсчета количества областей, что влияет на условие контроля цикла for, потенциально позволяя Indxe (sic) накапливаться до большого целочисленного значения. В совокупности эти отсутствующие проблемы с проверкой входных данных могут позволить злоумышленнику повредить SMRAM в приведенных ниже строках:
Код:
...
while (BiosRomMap[NumberOfRegions].Type != FbtsRomMapEos) {
NumberOfRegions++;
}
NumberOfRegions++;
RomMapSize = NumberOfRegions * sizeof (FBTS_INTERNAL_BIOS_ROM_MAP);
for (Indxe = 0; Indxe < (NumberOfRegions - 1); Indxe++) {
BiosRomMap[Indxe].Address = BiosRomMap[Indxe].Address
- PcdGet32(PcdFlashAreaBaseAddress)
+ PcdGet32(PcdFlashPartBaseAddress);
}
...
Наконец, перед возвратом сохраненный регистр RDI используется для копирования обновленного BiosRomMapобратно вызывающему объекту, вызвавшему обработчик SMI.
Код:
...
CopyMem ((VOID *)(UINTN)mH2OIhisi->ReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI),
(VOID *)BiosRomMap,
RomMapSize);
return IHISI_SUCCESS;
}
Но еще раз, поскольку RDI ранее не проверялся для предотвращения дублирования с SMRAM, CopyMem может перезаписать SMRAM.
Ошибка 2. IhisiServicesSmm: повреждение памяти в обработчике FTBS SMI
Insyde IHISI предоставляет подкоманду (AH=0x48), которая обрабатывается следующей функцией.
Обработчик SMI получает входные данные, контролируемые злоумышленником, через регистр сохранения состояния RSI. Ниже, ImageBlkPtrиспорчен вызывающей стороной и разыменовывается без проверки того, не перекрывает ли он SMRAM. Кроме того, вложенный указатель, ImageBlock, также разыменовывается без проверки перекрытия SMRAM.
Код:
EFI_STATUS SecureFlashFunction ( VOID )
{
...
ImageBlkPtr = (FBTS_SECURE_FLASH_IMAGE_BLOCK_STRUCTURE*)(UINTN)
IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RSI);
ImageBlock = ImageBlkPtr->BlockDataItem;
ImageBase = (UINT8*)(UINTN)(ImageBlock->ImageBlockAddress);
...
Затем, наконец, проверяется внутренний указатель с именем ImageBase, чтобы убедиться, что он не перекрывает SMRAM. Но при проверке на перекрытие вызов hisiProtBufferInCmdBuffer() использует значение ImageBlock->ImageBlockSize, которое также контролируется злоумышленником. Это эффективно позволяет легко обойти проверку работоспособности.
Код:
...
if (!IhisiProtBufferInCmdBuffer ((VOID *)ImageBase, (UINTN)(ImageBlock->ImageBlockSize)))
{
mFlashImageInfo.RemainingImageSize = 0;
return IHISI_BUFFER_RANGE_ERROR;
}
...
Позже в обработчике SMI вызывается функция MergeImageBlockWithoutCompress(). Эта функция также считывает регистр этапа сохранения RSI, чтобы получить указатель ImageBlkPtr. На этот раз функция действительно проверяет, перекрывает ли указатель SMRAM, но делает это только после разыменования его. Этот шаблон разыменования с последующей проверкой, скорее всего, является всего лишь неинтересным отказом в обслуживании.
Код:
In October of 2022, Intel’s Alder Lake BIOS source code was leaked online. The leaked code was comprised of firmware components that originated from three sources:
The independent BIOS vendor (IBV) named Insyde Software,
Intel’s proprietary Alder Lake BIOS reference code,
The Tianocore EDK2 open-source UEFI reference implementation.
I obtained a copy of the leaked code and began to hunt for vulnerabilities. This writeup focuses on the vulnerabilities that I found and reported to Insyde Software. These bugs span various System Management Mode (SMM) modules, including:
Insyde H2O Internal Soft-SMI Interface (IHISI) dispatcher
Flash BIOS Through SMI (FTBS) handlers
BIOS Guard SMI handlers
What is System Management Mode and Why is it Interesting?
Before diving into the bug details, let’s first take a brief detour to talk about System Management Mode. SMM is a highly privileged x86 operating mode. It has a variety of purposes, including control of hardware and peripherals, handling hardware interrupts, power management, and more. SMM is sometimes referred to as “Ring -2” using the protection ring nomenclature.
x86 Protection Levels
A CPU transitions to System Management Mode when a System Management Interrupt (SMI) is issued. A SMI can be generated from hardware or from software, such as by writing to an IO port. These interrupts are high priority and are unmaskable (e.g., they can’t be ignored).
SMM executes from a protected region of memory known as System Management RAM (SMRAM). The System-Management Range Register (SMRR) can be (*ahem* should be) programmed to restrict access to the SMRAM region, preventing external agents from accessing SMRAM. In other words, the OS should not be able to read or write SMRAM to directly influence SMM execution.
SMRAM Layout
SMM execution is transparent to the operating system. While a SMI handler is executing, the so-called SMI Rendezvous procedure will cause the other CPU cores to also enter SMM and wait. The OS can’t see or inspect what SMM is doing.
But on the other hand, SMM can influence OS execution. SMM has (nearly) full access to the platform’s DRAM. I say nearly here, because there are a few exceptions, such as certain DRAM carveouts that are owned by the even-more-highly-privileged firmware IPs, like AMD’s PSP or Intel’s CSME.
Beyond near-complete access to physical memory, SMM possesses additional powerful capabilities: It has full access to the platform’s SPI flash, and it can read/write all MSRs.
For these reasons, SMM is a desirable location for attackers to implant a bootkit. Such a bootkit will be simultaneously invisible to most anti-virus software and will also be highly privileged. If you want to read more on the topic of bootkits, Alex Matrosov has done an excellent job of documenting some examples. You might also be curious to check out the SmmBackdoor project.
One of the most essential security requirements for preventing runtime exploitation of SMM is that the integrity of SMRAM must be upheld. In other words: Simply don’t do memory corruption. But as we know, this is a tall order, especially because SMM firmware is written in C, where undefined behavior runs rampant and upholding memory safety is akin to the delicate circus act of balancing several spinning plates.
So unsurprisingly, over the years there have been countless examples of memory corruption vulnerabilities in SMM. For further reading, I encourage you to check out Xeno Kovah’s catalogue of Low Level PC/Server Attacks for an impressive timeline of SMM vulnerability research (among other cool firmware security topics!).
SMM Attack Surfaces
Within SMM, individual SMI handlers are registered using the gSmst->SmiHandlerRegister() function. Each handler has a unique GUID, which is used to select the appropriate handler when the OS invokes a SMI.
Arguments can be passed to the SMI handlers via a Communication Buffer in shared memory. Strict input validation of all arguments passed to a SMI handler is paramount to preserve the property of memory safety.
Another attack surface relates to various platform resources that are shared between SMM and other agents such as the host OS, peripherals, and firmware IPs. Here, race conditions such as time-of-check-time-of-use (TOCTOU) problems are also a significant concern. Some typical examples of shared resources that are consumed by SMM include the following:
SPI flash (e.g., EFI variables)
Memory-Mapped I/O (e.g., PCIe BARs)
Shared physical memory regions (e.g., the SMI Comm Buffer)
Model Specific Registers (MSRs)
Because these resources can be shared between multiple agents of differing privilege levels, a malicious low-privilege agent could tamper with the shared data while SMM is in the midst of processing it.
Another notable vulnerability class in SMM is the confused deputy. Confused deputy problems can occur when an attacker passes a pointer argument to SMM (e.g., the Comm Buffer) but forces the buffer to overlap with SMRAM. If the SMI handler fails to validate the pointer (don’t forget nested pointers too!), it may mistakenly read or write its own address space, believing it is reading SMI input or writing SMI output. This, of course, would have the undesirable result of corrupting SMRAM.
Communication Buffer Overlap
If you want to read more on these topics, check out the “A Tour Beyond BIOS: SMM Communication” whitepaper for an in depth description of these and other vulnerability classes that relate to SMM.
Finally, I want to add that Microsoft’s “Secured-Core PC” initiative is beginning to push the industry towards stronger SMM hardening through the use of an SMM Supervisor, which effectively deprivileges and isolates SMI handlers. Though, like most defensive technologies, creative people will find ways to break it. For example, last year Ilja van Sprundel of IOActive presented some excellent research that reveals several critical vulnerabilities in Microsoft’s MM Supervisor which is part of Project Mu.
The Focus of My Research
SMI handlers typically receive input arguments via the Communication Buffer, which resides in a region of shared memory that may be statically or dynamically defined. As mentioned above, the Comm Buffer must be positioned outside of SMRAM, and it is the duty of SMM to enforce this every time a SMI is handled.
However, SMI handlers may also receive arguments through general purpose registers. So how does that work? Well, when an SMI is issued by the OS, the processor state is saved, and execution context is switched to SMM. The saved general purpose registers reside inside SMRAM within the State Save Area. All of this is necessary because when a SMI handler completes, CPU state must be restored so that execution control can be returned to the caller.
High Level SMI Flow (from ABC to XYZ of SMM Drivers)
Of course, a malicious or compromised host OS could place any values in these registers prior to invoking the SMI. Per SMM’s threat model, the OS is completely untrusted, so the SMI handlers must be extremely cautious to validate all data that is read from the Save State Area.
For my research, I focused on the Insyde H2O (Hardware-2-Operating System) UEFI BIOS, which exposes an SMI interface named IHISI (Insyde H2O Internal Soft-SMI Interface). This interface is made up of many sub-commands which read and write these saved state registers, treating them as arguments to the sub-command handlers.
Let’s dive into the bug details!
Vulnerability Details
All these vulnerabilities share a common root cause (insufficient input validation) and a common impact (SMRAM corruption). Their details are summarized in the following table:
# Title CVE Insyde CVSS
1 IhisiServicesSmm: Save State Register Not Checked Before Use CVE-2023-22616 SA-2023022 6.4
2 IhisiServicesSmm: Memory Corruption in FTBS SMI Handler CVE-2023-22612 SA-2023019 8.1
3 IhisiServicesSmm: IHISI Subfunction Execution May Corrupt SMRAM. CVE-2023-22615 SA-2023021 6.4
4 IhisiServicesSmm: Write To Attacker Controlled Address CVE-2023-22613 SA-2023023 7.3
5 ChipsetSvcSmm: Insufficient Input Validation In BIOS Guard Updates CVE-2023-22614 SA-2023020 7.9
These issues were fixed in the Insyde release which occurred on April 10th 2023. They impact several different Insyde platforms, spanning Intel and AMD mobile and server devices. The specific platforms and versions can be found in the Insyde advisories, linked above.
Bug 1. IhisiServicesSmm: Save State Register Not Checked Before Use
The following SMI handler is an IHISI sub-function that is associated with Insyde’s Flash BIOS Through SMI (FTBS) functionality. The handler reads a structure pointer named BiosRomMap from RDI in the Save State Area.
EFI_STATUS EFIAPI FbtsGetWholeBiosRomMap ( VOID )
{
UINTN RomMapSize;
UINTN NumberOfRegions;
FBTS_INTERNAL_BIOS_ROM_MAP *BiosRomMap;
UINTN Indxe;
NumberOfRegions = 0;
BiosRomMap = (FBTS_INTERNAL_BIOS_ROM_MAP *) (UINTN)
mH2OIhisi->ReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI);
...
This pointer is not validated before it is dereferenced for both read and write operations. A confused deputy vulnerability arises when the caller forces RDI to point to SMRAM. This effectively coerces SMM into mistakenly accessing its own private memory space.
Next, the BiosRomMap array is walked to count the NumberOfRegions, which influences the for-loop sentinel condition, potentially allowing Indxe (sic) to accumulate to a large integer value. Together, these missing input validation problems may allow an attacker to corrupt SMRAM on the lines below:
...
while (BiosRomMap[NumberOfRegions].Type != FbtsRomMapEos) {
NumberOfRegions++;
}
NumberOfRegions++;
RomMapSize = NumberOfRegions * sizeof (FBTS_INTERNAL_BIOS_ROM_MAP);
for (Indxe = 0; Indxe < (NumberOfRegions - 1); Indxe++) {
BiosRomMap[Indxe].Address = BiosRomMap[Indxe].Address
- PcdGet32(PcdFlashAreaBaseAddress)
+ PcdGet32(PcdFlashPartBaseAddress);
}
...
Finally, before returning, the saved RDI register is used to copy the updated BiosRomMap back to the caller who invoked the SMI handler.
...
CopyMem ((VOID *)(UINTN)mH2OIhisi->ReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI),
(VOID *)BiosRomMap,
RomMapSize);
return IHISI_SUCCESS;
}
But once again, because RDI was not previously checked to prevent overlap with SMRAM, this CopyMem operation could overwrite SMRAM.
Bug 2. IhisiServicesSmm: Memory Corruption in FTBS SMI Handler
The Insyde IHISI exposes a sub-command (AH=0x48) which is handled by the following function.
The SMI handler receives attacker-controlled input through the save-state register, RSI. Below, ImageBlkPtr is tainted by the caller, and is dereferenced without checking whether it overlaps SMRAM. Additionally, the nested pointer, ImageBlock, is also dereferenced without checking for SMRAM overlap.
EFI_STATUS SecureFlashFunction ( VOID )
{
...
ImageBlkPtr = (FBTS_SECURE_FLASH_IMAGE_BLOCK_STRUCTURE*)(UINTN)
IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RSI);
ImageBlock = ImageBlkPtr->BlockDataItem;
ImageBase = (UINT8*)(UINTN)(ImageBlock->ImageBlockAddress);
...
Next, the inner-most pointer named ImageBase is finally checked to ensure it doesn’t overlap SMRAM. But when checking for overlap, the call to IhisiProtBufferInCmdBuffer() uses the ImageBlock->ImageBlockSize value, which also happens to be attacker controlled. This effectively allows this sanity check to be easily circumvented.
...
if (!IhisiProtBufferInCmdBuffer ((VOID *)ImageBase, (UINTN)(ImageBlock->ImageBlockSize)))
{
mFlashImageInfo.RemainingImageSize = 0;
return IHISI_BUFFER_RANGE_ERROR;
}
...
Later in the SMI handler, MergeImageBlockWithoutCompress() is called. This function also reads the RSI save-stage register to get the ImageBlkPtr pointer. This time, the function does check whether the pointer overlaps SMRAM, but it does so only after dereferencing it. This dereference-then-validate pattern is most likely only an uninteresting denial of service.
EFI_STATUS MergeImageBlockWithoutCompress (
IN EFI_PHYSICAL_ADDRESS TargetImageAddress
)
{
...
TotalImageSize = mFlashImageInfo.TotalImageSize - mFlashImageInfo.RemainingImageSize;
ImageBlkPtr = (FBTS_SECURE_FLASH_IMAGE_BLOCK_STRUCTURE*)(UINTN)
IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RSI);
...
NumberOfImageBlk = ImageBlkPtr->BlockNum;
if (!IhisiProtBufferInCmdBuffer ((VOID *) ImageBlkPtr, NumberOfImageBlk)) {
return IHISI_BUFFER_RANGE_ERROR;
}
...
Однако, что более интересно, так это использование указателя ImageBlock, потому что из предыдущего анализа мы знаем, что этот указатель контролируется злоумышленником. Если он указывает на память, контролируемую злоумышленником, он подвержен уязвимостям TOCTOU. В результате ImageBlock->ImageBlockSize может изменяться между несколькими разыменованиями, показанными ниже.
Код:
...
ImageBlock = ImageBlkPtr->BlockDataItem;
...
Destination = (UINT8 *) (UINTN) (TargetImageAddress + TotalImageSize);
for (Index = 0; Index < NumberOfImageBlk; Index++) {
if (!FeaturePcdGet(PcdH2OIhisiCmdBufferSupported)
ImageBlock->ImageBlockSize > UTILITY_ALLOCATE_BLOCK_SIZE)
{
// The max block size need co-operate with utility
return EFI_INVALID_PARAMETER;
}
CopyMem ((VOID *) Destination,
(UINT8 *)(UINTN) ImageBlock->ImageBlockAddress,
(UINTN) ImageBlock->ImageBlockSize);
...
}
Если злоумышленник, способный к DMA, выигрывает это условие гонки, он может изменить ImageBlock->ImageBlockSize после того, как он был проверен, но до того, как он будет использован в вызове CopyMem(). Это приводит к повреждению памяти за пределами конечной области памяти назначения. Любопытно, что указатель назначения изначально был получен из переменной EFI “SecureFlashInfo” (не показана для краткости), которая хранится с атрибутами BS+RT+NV, что указывает на то, что ее значение также контролируется вредоносной ОС хоста. В заключение, это означает, что злоумышленник контролирует адрес назначения, адрес источника и параметры размера, которые передаются в CopyMem(). Это мощный примитив повреждения памяти "write-what-where"
Ошибка 3. IhisiServicesSmm: Выполнение подфункции IHISI может привести к повреждению SMRAM
Следующий блок кода показывает диспетчер основной подфункции IHISI. Он просматривает таблицу подфункций, находит зарегистрированную подфункцию, которая соответствует коду команды, а затем вызывает функцию обработчика, как показано ниже:
Код:
EFI_STATUS EFIAPI IhisiProtExecuteCommandByPriority (
IN UINT32 CmdCode,
IN UINT8 FromPriority,
IN UINT8 ToPriority
)
{
EFI_STATUS Status;
LIST_ENTRY *Link;
IHISI_COMMAND_ENTRY *CmdNode;
IHISI_FUNCTION_ENTRY *FunctionNode;
CmdNode = IhisiFindCommandEntry (CmdCode);
...
for (Link = GetFirstNode ( CmdNode->FunctionChain);
!IsNull ( CmdNode->FunctionChain, Link);
Link = GetNextNode ( CmdNode->FunctionChain, Link))
{
FunctionNode = IHISI_FUNCTION_ENTRY_FROM_LINK (Link);
if (FunctionNode->Priority > ToPriority || FunctionNode->Priority < FromPriority) {
continue;
}
Status = FunctionNode->Function();
...
После возврата подфункции, и если CmdCode равен OEMSFOEMExCommunication, содержимое буфера будет скопировано обратно вызывающей стороне в качестве выходных данных SMI. Адрес назначения для этой операции CopyMem() определяется вызывающей стороной обработчика SMI, поскольку он был передан в регистре состояния сохранения RCX.
Код:
...
if (CmdCode == OEMSFOEMExCommunication) {
CopyMem( (AP_COMMUNICATION_DATA_TABLE*) (UINTN)
IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX),
mApCommDataBuffer,
sizeof (AP_COMMUNICATION_DATA_TABLE) );
}
...
Проблема здесь в том, что когда злоумышленник контролирует содержимое RCX, он может заставить приведенный выше код записать mApCommDataBuffer в контролируемое злоумышленником местоположение в SMRAM.
Оценивая влияние этого, мы должны проверить, правильно ли каждая подфункция IHISI проверяет RCX, прежде чем возвращаться к диспетчеру. Соответствующие подфункции, связанные с кодом команды OEMSFOEMExCommunication, перечислены ниже:
Код:
STATIC IHISI_REGISTER_TABLE OEM_EXT_COMMON_REGISTER_TABLE[] = {
{ OEMSFOEMExCommunication, "S41Kn_CommuSaveRegs", KernelCommunicationSaveRegs },
{ OEMSFOEMExCommunication, "S41Cs_ExtDataCommun", ChipsetOemExtraDataCommunication },
{ OEMSFOEMExCommunication, "S41OemT01Vbios00000", OemIhisiS41T1Vbios },
{ OEMSFOEMExCommunication, "S41OemT54LogoUpdate", OemIhisiS41T54LogoUpdate },
{ OEMSFOEMExCommunication, "S41OemT55CheckSignB", OemIhisiS41T55CheckBiosSignBySystemBios },
{ OEMSFOEMExCommunication, "S41OemReservedFun00", OemIhisiS41ReservedFunction },
{ OEMSFOEMExCommunication, "S41Kn_T51EcIdelTrue", KernelT51EcIdelTrue },
{ OEMSFOEMExCommunication, "S41Kn_ExtDataCommun", KernelOemExtraDataCommunication },
{ OEMSFOEMExCommunication, "S41Kn_T51EcIdelFals", KernelT51EcIdelFalse },
{ OEMSFOEMExCommunication, "S41OemT50Oa30RWFun0", OemIhisiS41T50a30ReadWrite },
...
После тщательной проверки мы определили, что большинство из этих подфункций IHISI выполняют строгую проверку указателя, хранящегося в RCX. Например, ниже показан первый обработчик, KernelCommunicationSaveRegs(). Здесь мы можем наблюдать, что ApCommDataBuffer (указатель, который был считан из RCX) проверяется, чтобы убедиться, что он правильно находится внутри буфера связи.
Код:
EFI_STATUS EFIAPI KernelCommunicationSaveRegs ( VOID )
{
AP_COMMUNICATION_DATA_TABLE *ApCommDataBuffer;
UINTN BufferSize;
mRomBaseAddress = 0;
mRomSize = 0;
ApCommDataBuffer = (AP_COMMUNICATION_DATA_TABLE*) (UINTN)
IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX);
if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer,
sizeof(AP_COMMUNICATION_DATA_TABLE)))
{
return IHISI_BUFFER_RANGE_ERROR;
}
...
BufferSize = ApCommDataBuffer->StructureSize;
if (BufferSize < sizeof(AP_COMMUNICATION_DATA_TABLE)) {
BufferSize = sizeof(AP_COMMUNICATION_DATA_TABLE);
}
if (!IhisiProtBufferInCmdBuffer ((VOID *) ApCommDataBuffer, BufferSize)) {
return IHISI_BUFFER_RANGE_ERROR;
}
...
}
Однако есть две подфункции, которые не проверяют RCX:
KernelT51EcIdelTrue()
KernelT51EcIdelFalse()
Эта оплошность, скорее всего, является следствием того факта, что эти подфункции не используют RCX, поэтому, возможно, разработчик предположил, что нет необходимости проверять RCX. Однако, несмотря на то, что эти подфункции никогда не используют RCX, диспетчер IhisiProtExecuteCommandByPriority() все равно будет использовать RCX в качестве адреса назначения для операции CopyMem(). Следовательно, если злоумышленник установит адрес в RCX, который перекрывает SMRAM, перед вызовом подфункций S41Kn_T51EcIdelTrue или S41Kn_T51EcIdelFalse, они могут повредить SMRAM содержимым буфера связи AP.
Ошибка 4. IhisiServicesSmm: Запись на адрес, контролируемый злоумышленником
Следующий обработчик SMI считывает указатель структуры с именем Output Data из регистра состояния сохранения RCX, как показано ниже:
Код:
STATIC EFI_STATUS ReadDefaultSettingsToFactoryCopy ( VOID )
{
OUTPUT_DATA_STRUCTURE *OutputData;
UINT64 FactoryCopySize;
OutputData = (OUTPUT_DATA_STRUCTURE *) (UINTN)
IhisiProtReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX);
...
Затем обработчик SMI выполняет запись в поля этой структуры без проверки. OutputDataдля перекрытия с SMRAM.
Код:
...
OutputData->BlockSize = COMMON_REGION_BLOCK_SIZE_4K;
FactoryCopySize = FdmGetSizeById (...);
...
if (FactoryCopySize == 0x10000) {
OutputData->DataSize = COMMON_REGION_SIZE_64K;
} else {
OutputData->DataSize = COMMON_REGION_REPORT_READ_SIZE;
OutputData->PhysicalDataSize = (UINT32) FactoryCopySize;
}
...
Рискую показаться заезженной пластинкой: еще раз повторю, что это простая уязвимость, связанная с повреждением памяти SMM.
Ошибка 5. ChipsetSvcSmm: Недостаточная проверка ввода в обновлениях BIOS Guard
BIOS Guard - это функция безопасности, входящая в маркетинговую программу Intel “Hardware Shield”. Это усложняет процесс обновления BIOS flash, ограничивая доступ к SPI flash через BIOS Guard ACM, который проверяет подлинность обновлений BIOS. Существует мало общедоступной документации по BIOS Guard, но в этом докладе раскрываются некоторые аспекты дизайна, которые Алекс восстановил с помощью обратного инжиниринга. Следующая уязвимость затрагивает SMM-модуль Insyde, который анализирует заголовок обновления BIOS Guard, расположение которого показано ниже:
Ниже InputDataBuffer считывается из RSI и указывает на приведенную выше структуру обновления BIOS Guard. Этот указатель разыменовывается для вычисления смещения сертификата BIOS Guard (BgupcOffset) без предварительной проверки того, перекрывает ли указатель SMRAM. Поскольку ScriptSectionSize и DataSectionSize (оба типа UINT32) повреждены, BgupcOffset также следует считать поврежденным и может принимать любое 32-разрядное целочисленное значение.
Код:
EFI_STATUS BiosGuardUpdateWrite ( VOID )
{
...
UINT32 BgupcSize;
UINT32 BgupcOffset;
UINT32 BufferSize;
EFI_PHYSICAL_ADDRESS BgupCertificate;
UINT8 *InputDataBuffer;
UINT32 DataSize;
...
InputDataBuffer = (UINT8*)(UINTN)mH2OIhisi->ReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RSI);
BgupcOffset = sizeof(BGUP_HEADER)
+ ((BGUP *) InputDataBuffer)->BgupHeader.ScriptSectionSize
+ ((BGUP *) InputDataBuffer)->BgupHeader.DataSectionSize;
...
Затем из RDI считывается значение bufferSize, и оно используется для проверки того, находится ли входной буфер внутри командного буфера. Однако в этом коде отсутствуют строгие проверки, гарантирующие, что размер буфера достаточно велик. Если размер буфера оказался меньше размера структуры BGUP_HEADER, то более ранние разыменования указателя (при чтении элементов из BgupHeader) могли бы получить доступ к памяти за пределами входного буфера, что привело бы к чтению вне границ.
Код:
...
BufferSize = mH2OIhisi->ReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI);
BgupCertificate = (EFI_PHYSICAL_ADDRESS) (mBiosGuardMemAddress
+ mBiosGuardMemSize
- BGUPC_MEMORY_OFFSET);
if (!mH2OIhisi->BufferInCmdBuffer ((VOID *) InputDataBuffer, BufferSize)) {
return EFI_INVALID_PARAMETER;
}
...
Затем проверяется BgupcSize, чтобы убедиться, что он соответствует размеру буфера. Однако эту проверку работоспособности также можно обойти, поскольку злоумышленник контролирует обе части условного выражения — как BgupcOffset, так и bufferSize.
Код:
...
if ((BgupcOffset + BgupcSize) != BufferSize) {
return EFI_INVALID_PARAMETER;
}
...
Последним шагом, выполняемым перед запуском BIOS Guard ACM, является использование управляемого злоумышленником BgupcOffset (который может быть очень большим) для копирования сертификата и обновления данных. Это показано ниже:
Код:
...
ZeroMem ((VOID *)(UINT64) mBiosGuardMemAddress, mBiosGuardMemSize);
CopyMem ((VOID *)(UINT64) mBiosGuardMemAddress, InputDataBuffer, BgupcOffset);
CopyMem ((VOID *) BgupCertificate, InputDataBuffer + BgupcOffset, BgupcSize);
...
Приведенные выше вызовы CopyMem() могут привести к повреждению SMRAM, когда перезаписывается память за пределами области mBiosGuardMemAddress.
Последнее редактирование: