Безопасная реализация MOR
Итоги
- Поведение MorLock, редакция 2
Последнее обновление
- Август 2020 г.
Область применения
Windows 10
Изготовители оборудования и поставщики BIOS, которые хотят поддерживать функцию Credential Guard Windows 10.
Официальные спецификации
Рекомендуем прочесть
Запись блога: защита BitLocker от холодных атак (и других угроз)
Технический документ: Обзор за пределами BIOS с поддержкой UEFI TPM2 в EDKII
Защита извлеченных учетных данных домена с помощью Credential Guard
Обзор
В этом разделе описывается поведение и использование переменной 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*, ...). Для MemoryOverwriteRequestControlLock
(и MemoryOverwriteRequestControl
) 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
Эти блок-схемы показывают ожидаемое поведение реализации:
Инициализация
Поток SetVariable
Разблокируемый поток состояния для SetVariable
Заблокированный поток состояния для SetVariable
Поток для GetVariable
См. также
Требования UEFI, применимые ко всем выпускам Windows на платформах SoC
Защита BitLocker от холодных атак (и других угроз)
Обзор за пределами BIOS с поддержкой UEFI TPM2 в EDKII
Защита извлеченных учетных данных домена с помощью Credential Guard