總結
- MorLock 的行為,修訂版 2
上次更新
- 2020 年 8 月
適用對象
Windows 10
想要支援 Windows 10 Credential Guard 功能的 OEM 和 BIOS 廠商。
官方規格
建議的閱讀資料
概觀
本主題說明 UEFI 變數修訂 2 的 MemoryOverwriteRequestControlLock 行為和使用方式。
為了防止進階記憶體攻擊,現有的系統 BIOS 安全性風險降低 MemoryOverwriteRequestControl 已改善,以支援鎖定以防禦新的威脅。 威脅模型已擴展以包括主機作業系統核心作為攻擊者,因此在核心許可權層級執行的 ACPI 和 UEFI 執行階段服務不被信任。 類似於安全開機實作,MorLock 應該在主機 OS 核心無法竄改的特殊許可權韌體執行內容中實作, (例如,系統管理模式、TrustZone、BMC 等等) 。 介面是以 UEFI 變數服務為基礎,這些服務會在 UEFI 規格 2.5 版第 7.2 節中描述,名為「變數服務」。
這種緩解措施稱為 MorLock,必須在所有新系統上實施,而不僅限於具有可信任平台模組的系統。 修訂版 2 新增了一項新功能 unlock,以減輕開機效能問題,尤其是在大型記憶體系統上。
關於設定 MOR 位狀態的 ACPI _DSM控制方法 (如 電腦用戶端工作群組平臺重設攻擊風險降低規格 1.10 版 (PDF 下載) 的第 6 節所述) ,建議您從新式 BIOS 實作中移除此_DSM方法。
不過,如果 BIOS 實作此_DSM方法,則必須遵循 MorLock 的狀態。 如果 MorLock 已鎖定,無論有沒有金鑰,此_DSM方法都必須無法變更 MOR,並傳回對應於「一般失敗」的值 1。 未定義 ACPI 機制來開鎖 MorLock 修訂版 2。
請注意,自 Windows 7 以來,Windows 沒有直接叫用此_DSM方法,並認為它已被取代。 當 Windows 叫用 ACPI _PTS 作為 MOR 自動偵測全新關機的實作時,某些 BIOS 會間接 叫用此_DSM方法 (如 電腦用戶端工作群組平臺重設攻擊風險降低規格 1.10 版的第 2.3 節所述) (PDF 下載) 。
此 ACPI _PTS MOR 自動偵測實作有安全性缺陷,不應使用。
記憶體覆寫請求控制鎖 (MemoryOverwriteRequestControlLock)
包含改進的緩解措施的 BIOS 會在早期啟動期間建立此 UEFI 變數:
供應商指南:{BB983CCF-151D-40E1-A07B-4A17BE168292}
名稱:MemoryOverwriteRequestControlLock
屬性: NV+BS+RT
GetVariable 資料參數中的值:0x0(已解鎖);0x1(無鑰匙上鎖);0x2(用鑰匙鎖定)
資料參數中的SetVariable值:0x0(已解鎖);0x1(鎖定)
使用 SetVariable 鎖定
每次開機時,BIOS 都會在開機裝置選取 (BDS) 階段 (DRIVER####、SYSPREP##、BOOT####、*RECOVERY* 等) 之前初始化 MemoryOverwriteRequestControlLock 為單位元組值 0x00 (表示 已解除鎖定) 。 對於 MemoryOverwriteRequestControlLock (和 MemoryOverwriteRequestControl),BIOS 應防止刪除變數,且屬性必須釘選至 NV+BS+RT。
當第一次呼叫 SetVariable for MemoryOverwriteRequestControlLock 時,會在 Data 中傳遞有效的非零值,兩者的MemoryOverwriteRequestControlLockMemoryOverwriteRequestControl存取模式都會變更為唯讀,指出它們已鎖定。
修訂版 1 實作僅接受單一位元組的 0x00 或 0x01 MemoryOverwriteRequestControlLock。
修訂版 2 也接受代表共用秘密金鑰的 8 位元組值。 如果在 SetVariable 中指定任何其他值,呼叫會失敗,狀態為 EFI_INVALID_PARAMETER。 若要產生該金鑰,請使用高品質的熵來源,例如信任平台模組或硬體隨機數產生器。
設定金鑰之後,呼叫端和韌體都應該將此金鑰的複本儲存在機密性保護的位置,例如 IA32/X64 上的 SMRAM 或具有受保護儲存體的服務處理器。
取得系統狀態
在修訂版 2 中,當 MemoryOverwriteRequestControlLock 和 MemoryOverwriteRequestControl 變數鎖定時,會先使用常數時間演算法針對已註冊的索引鍵,檢查 SetVariable(針對這些變數)的呼叫。 如果兩個金鑰都存在且相符,變數會轉換回解除鎖定狀態。 在第一次嘗試之後,或如果未註冊金鑰,則後續嘗試設定此變數會失敗,並返回EFI_ACCESS_DENIED以防止暴力破解攻擊。 在這種情況下,系統重新啟動應該是解鎖變數的唯一方法。
作業系統會呼叫 GetVariable 來偵測 的MemoryOverwriteRequestControlLock存在及其狀態。 然後,系統可以透過將 MemoryOverwriteRequestControlLock 值設為 0x1 來鎖定 MemoryOverwriteRequestControl 的當前值。 或者,它可以指定一個金鑰,以便在從記憶體中安全清除秘密資料後啟用未來解鎖。
呼叫 GetVariable 會傳回 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 的流程
另請參閱
適用於SoC平臺上所有 Windows 版本的 UEFI 需求
PC 用戶端工作群組平台重設攻擊緩解規格,1.10 版 (PDF 下載)