Implementazione sicura di MOR

Riepilogo

  • Comportamento di MorLock, revisione 2

Ultimo aggiornamento

  • Agosto 2020

Si applica a

  • Windows 10

  • Oem e fornitori di BIOS che vogliono supportare la funzionalità Credential Guard di Windows 10.

Specifiche ufficiali

Panoramica

Questo argomento descrive il comportamento e l'utilizzo per la MemoryOverwriteRequestControlLock variabile UEFI, revisione 2.

Per evitare attacchi di memoria avanzati, la mitigazione della sicurezza BIOS del sistema esistente MemoryOverwriteRequestControl è migliorata per supportare il blocco per difendere contro le nuove minacce. Il modello di minaccia viene espanso per includere il kernel del sistema operativo host come avversario, pertanto i servizi di runtime ACPI e UEFI in esecuzione a livello di privilegi kernel non sono attendibili. Analogamente alle implementazioni di avvio sicuro, MorLock deve essere implementato in un contesto di esecuzione del firmware con privilegi che non può essere manomesso dal kernel del sistema operativo host, ad esempio modalità di gestione del sistema, TrustZone, BMC e così via. L'interfaccia è basata su servizi variabili UEFI, descritti nella specifica UEFI versione 2.5, sezione 7.2 denominata "Servizi variabili".

Questa mitigazione, denominata MorLock, deve essere implementata in tutti i nuovi sistemi e non solo per i sistemi con moduli di piattaforma attendibili. La revisione 2 aggiunge una nuova funzionalità, sblocco, per attenuare i problemi di prestazioni di avvio, soprattutto nei sistemi di memoria di grandi dimensioni.

Per quanto riguarda il metodo di controllo ACPI _DSM per impostare lo stato di bit MOR (come descritto nella sezione 6 della specifica di mitigazione degli attacchi della piattaforma di ripristino della piattaforma di lavoro client PC, versione 1.10 (download PDF), è consigliabile rimuovere questo metodo _DSM dalle implementazioni moderne del BIOS.

Tuttavia, se un BIOS implementa questo metodo _DSM, deve rispettare lo stato di MorLock. Se MorLock è bloccato, con o senza una chiave, questo metodo _DSM deve non modificare MOR e restituire un valore pari a "Errore generale". Non è definito alcun meccanismo ACPI per sbloccare MorLock revisione 2.

Si noti che Windows non ha richiamato direttamente questo metodo _DSM da Windows 7 e lo considera deprecato. Alcuni BIOS richiamano indirettamente questo metodo _DSM quando Windows richiama i _PTS ACPI come implementazione del rilevamento automatico MOR di Arresto pulito (come descritto nella sezione 2.3 della specifica di mitigazione degli attacchi di reimpostazione degli attacchi del gruppo di lavoro client PC, versione 1.10 (download PDF).

Questa _PTS'implementazione del rilevamento automatico MOR è scarsa e non deve essere usata.

MemoryOverwriteRequestControlLock

IL BIOS contenente la mitigazione migliorata crea questa variabile UEFI durante l'avvio iniziale:

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

Nome:MemoryOverwriteRequestControlLock

Attributi: NV+BS+RT

Valore GetVariable nel parametro Data : 0x0 (sbloccato); 0x1 (bloccato senza chiave); 0x2 (bloccato con chiave)

Valore SetVariable nel parametro Data : 0x0 (sbloccato); 0x1 (bloccato)

Blocco con SetVariable

In ogni avvio, IL BIOS verrà inizializzato MemoryOverwriteRequestControlLock in un valore a byte singolo di 0x00 (che indica lo sblocco) prima della fase di selezione del dispositivo di avvio (BDS) (DRIVER#, SYSPREP#, BOOT#, *RECOVERY*, ...). Per MemoryOverwriteRequestControlLock (e MemoryOverwriteRequestControl), IL BIOS impedisce l'eliminazione della variabile e degli attributi deve essere aggiunto a NV+BS+RT.

Quando SetVariable per MemoryOverwriteRequestControlLock viene chiamato passando un valore diverso da zero valido in Dati, la modalità di accesso per entrambi MemoryOverwriteRequestControlLock e MemoryOverwriteRequestControl viene modificata in sola lettura, indicando che sono bloccati.

Le implementazioni della revisione 1 accettano solo un singolo byte di 0x00 o 0x01 per MemoryOverwriteRequestControlLock.

La revisione 2 accetta inoltre un valore a 8 byte che rappresenta una chiave privata condivisa. Se viene specificato qualsiasi altro valore in SetVariable, la chiamata ha esito negativo con lo stato EFI_INVALID_PARAMETER. Per generare tale chiave, usare un'origine di entropia di alta qualità, ad esempio il generatore di numeri casuali della piattaforma attendibile o hardware.

Dopo aver impostato una chiave, il chiamante e il firmware devono salvare copie di questa chiave in una posizione protetta da riservatezza, ad esempio SMRAM in IA32/X64 o un processore di servizi con archiviazione protetta.

Recupero dello stato del sistema

Nella revisione 2, quando le variabili e MemoryOverwriteRequestControl sono bloccate, le MemoryOverwriteRequestControlLock chiamate di SetVariable (per tali variabili) vengono prima controllate sulla chiave registrata usando un algoritmo di tempo costante. Se entrambe le chiavi sono presenti e corrispondono, le variabili passano nuovamente a uno stato sbloccato. Dopo questo primo tentativo o se non viene registrata alcuna chiave, i tentativi successivi di impostare questa variabile non riescono con EFI_ACCESS_DENIED per evitare attacchi di forza bruta. In tal caso, il riavvio del sistema sarà l'unico modo per sbloccare le variabili.

Il sistema operativo rileva la presenza di MemoryOverwriteRequestControlLock e il relativo stato chiamando GetVariable. Il sistema può quindi bloccare il valore corrente impostando MemoryOverwriteRequestControl il MemoryOverwriteRequestControlLock valore su 0x1. In alternativa, può specificare una chiave per abilitare lo sblocco in futuro dopo che i dati segreti sono stati eliminati in modo sicuro dalla memoria.

Chiamata di GetVariable per MemoryOverwriteRequestControlLock restituisce 0x0, 0x1 o 0x2 per indicare lo sblocco, il blocco senza chiave o lo stato di blocco con gli stati della chiave.

L'impostazione MemoryOverwriteRequestControlLock non esegue il commit su flash (modifica solo lo stato di blocco interno). Ottenere la variabile restituisce lo stato interno e non espone mai la chiave.

Esempio di utilizzo dal sistema operativo:

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);

Flusso di implementazione di MorLock

Questi diagrammi di flusso mostrano il comportamento previsto dell'implementazione:

Inizializzazione

inizializzazione morlock.

Flusso setVariable

flusso di programmazione morlock.

Flusso di stato sbloccato per SetVariable

flusso sbloccato con morlock.

Flusso di stato bloccato per SetVariable

flusso bloccato morlock.

Flusso per GetVariable

morlock getvariable.

Vedi anche

Requisiti UEFI applicabili a tutte le edizioni di Windows nelle piattaforme SoC

Specifica di mitigazione degli attacchi per il gruppo di lavoro client PC, versione 1.10 (download PDF)

Protezione di BitLocker da attacchi ad accesso sporadico (e altre minacce)

Tour Beyond BIOS con il supporto TPM2 UEFI in EDKII

Proteggere le credenziali di dominio derivate con Credential Guard

Specifiche UEFI