Поделиться через


Безопасная реализация MOR

Итоги

  • Поведение MorLock, редакция 2

Последнее обновление

  • Август 2020 г.

Область применения

  • Windows 10

  • Изготовители оборудования и поставщики BIOS, которые хотят поддерживать функцию Credential Guard Windows 10.

Официальные спецификации

Обзор

В этом разделе описывается поведение и использование переменной MemoryOverwriteRequestControlLock UEFI версии 2.

Чтобы предотвратить расширенные атаки на память, существующей системной системной системе по устранению рисков MemoryOverwriteRequestControl улучшена поддержка блокировки для защиты от новых угроз. Модель угроз расширяется, чтобы включить ядро ОС узла в качестве злоумышленника, поэтому службы среды выполнения ACPI и UEFI, выполняемые на уровне привилегий ядра, не являются доверенными. Аналогично реализации безопасной загрузки, MorLock следует реализовать в привилегированном контексте выполнения встроенного ПО, который не может быть изменен ядром ос узла (например, режим управления системой, TrustZone, BMC и т. д.). Интерфейс основан на службах переменных UEFI, которые описаны в спецификации UEFI версии 2.5, разделе 7.2 с именем "Службы переменных".

Это решение, называемое MorLock, должно быть реализовано во всех новых системах, а не только в системах с доверенными платформенными модулями. Версия 2 добавляет новую возможность, разблокировку, чтобы устранить проблемы с производительностью загрузки, особенно в крупных системах памяти.

Что касается метода управления ACPI _DSM для настройки битового состояния MOR (как описано в разделе 6 спецификации сброса рисков атак для клиентских рабочих групп пк, версия 1.10 (скачивание PDF)), мы рекомендуем удалить этот метод _DSM из современных реализаций BIOS.

Однако если BIOS реализует этот метод _DSM, он должен уважать состояние MorLock. Если morLock заблокирован, с ключом или без него, этот метод _DSM должен не изменить MOR и вернуть значение 1, соответствующее "General Failure". Для разблокировки MorLock версии 2 не определен механизм ACPI.

Обратите внимание, что Windows не напрямую вызвал этот метод _DSM с Windows 7 и считает его устаревшим. Некоторые BIOS косвенно вызывает этот метод _DSM, когда Windows вызывает ACPI _PTS в качестве реализации автоматического обнаружения автоматического отключения MOR (как описано в разделе 2.3 спецификации сброса атак на платформу сброса атак клиента ПК версии 1.10 (скачивание PDF)).

Эта реализация ACPI _PTS автоматического обнаружения MOR является недостаточной и не должна использоваться.

MemoryOverwriteRequestControlLock

BIOS, содержащая улучшенную защиту, создает эту переменную UEFI во время ранней загрузки:

VendorGuid: {BB983CCF-151D-40E1-A07B-4A17BE168292}

Имя: MemoryOverwriteRequestControlLock

Атрибуты: NV+BS+RT

Значение GetVariable в параметре Data : 0x0 (разблокировано); 0x1 (заблокирован без ключа); 0x2 (заблокировано с помощью ключа)

Значение SetVariable в параметре Data : 0x0 (разблокировано); 0x1 (заблокировано)

Блокировка с помощью SetVariable

При каждой загрузке BIOS должен инициализировать MemoryOverwriteRequestControlLock однобайтовое значение 0x00 (указывающее , разблокировано) перед этапом выбора загрузочного устройства (BDS) (DRIVER#, SYSPREP#, BOOT#, *RECOVERY*, ...). Для MemoryOverwriteRequestControlLockMemoryOverwriteRequestControl) BIOS не должен препятствовать удалению переменной и атрибутов, которые должны быть закреплены на NV+BS+RT.

При первом вызове SetVariable MemoryOverwriteRequestControlLock путем передачи допустимого ненулевого значения в Data режим доступа для обоих MemoryOverwriteRequestControlLock и MemoryOverwriteRequestControl изменяется на только для чтения, указывая, что они заблокированы.

Реализация версии 1 принимает только один байт 0x00 или 0x01.MemoryOverwriteRequestControlLock

Версия 2 также принимает 8-байтовое значение, представляющее общий секретный ключ. Если любое другое значение указано в SetVariable, вызов завершается сбоем с состоянием EFI_INVALID_PARAMETER. Чтобы создать этот ключ, используйте высококачественный источник энтропии, например доверенный модуль платформы или генератор случайных чисел оборудования.

После установки ключа вызывающий объект и встроенное ПО должны сохранять копии этого ключа в защищенном конфиденциальном расположении, например SMRAM в IA32/X64 или обработчике служб с защищенным хранилищем.

Получение состояния системы

В редакции 2 при MemoryOverwriteRequestControlLock блокировке и MemoryOverwriteRequestControl переменных вызовы SetVariable (для этих переменных) сначала проверяются на зарегистрированный ключ с помощью алгоритма постоянного времени. Если оба ключа присутствуют и соответствуют, переменные возвращаются в разблокированное состояние. После первой попытки или если ключ не зарегистрирован, последующие попытки установить эту переменную завершаются ошибкой с EFI_ACCESS_DENIED, чтобы предотвратить атаки методом подбора. В этом случае перезагрузка системы должна быть единственным способом разблокировки переменных.

Операционная система обнаруживает наличие MemoryOverwriteRequestControlLock и его состояние путем вызова GetVariable. Затем система может заблокировать текущее значение MemoryOverwriteRequestControl , задав MemoryOverwriteRequestControlLock значение 0x1. Кроме того, он может указать ключ для включения разблокировки в будущем после безопасной очистки секретных данных из памяти.

Вызов GetVariable для MemoryOverwriteRequestControlLock возвращаемых 0x0, 0x1 или 0x2 для указания разблокированных, заблокированных без ключа или заблокированных с помощью состояний ключей.

Параметр MemoryOverwriteRequestControlLock не фиксирует вспышку (просто изменяет состояние внутренней блокировки). Получение переменной возвращает внутреннее состояние и никогда не предоставляет ключ.

Пример использования операционной системой:

if (gSecretsInMemory)
{
    char data = 0x11;
    SetVariable(MemoryOverwriteRequestControl, sizeof(data), &data);
}

// check presence
status = GetVariable(MemoryOverwriteRequestControlLock, &value);  

if (SUCCESS(status))
{
    // first attempt to lock and establish a key
    // note both MOR and MorLock are locked if successful

    GetRNG(8, keyPtr);
    status = SetVariable(MemoryOverwriteRequestControlLock, 8, keyPtr);

    if (status != EFI_SUCCESS)
    {
        // fallback to revision 1 behavior
        char data = 0x01;
        status = SetVariable(MemoryOverwriteRequestControlLock, 1, &data);
        if (status != EFI_SUCCESS) { // log error, warn user }
    }
}
else
{
    // warn user about potentially unsafe system
}

// put secrets in memory

// … time passes …

// remove secrets from memory, flush caches

SetVariable(MemoryOverwriteRequestControlLock, 8, keyPtr);

Поток реализации MorLock

Эти блок-схемы показывают ожидаемое поведение реализации:

Инициализация

инициализация morlock.

Поток SetVariable

поток программирования morlock.

Разблокируемый поток состояния для SetVariable

блок блокировки разблокирован.

Заблокированный поток состояния для SetVariable

блок блокировок заблокирован.

Поток для GetVariable

morlock getvariable.

См. также

Требования UEFI, применимые ко всем выпускам Windows на платформах SoC

Спецификация сброса атак на платформу сброса клиентских рабочих групп ПК версии 1.10 (скачивание PDF)

Защита BitLocker от холодных атак (и других угроз)

Обзор за пределами BIOS с поддержкой UEFI TPM2 в EDKII

Защита извлеченных учетных данных домена с помощью Credential Guard

Спецификации UEFI