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