Partilhar via


Implementação segura de MOR

Resumo

  • Comportamento de MorLock, revisão 2

Última atualização

  • Agosto de 2020

Aplica-se a

  • Windows 10

  • OEMs e fornecedores de BIOS que desejam oferecer suporte ao recurso Credential Guard do Windows 10.

Especificações oficiais

Visão geral

Este tópico descreve o comportamento e o uso da MemoryOverwriteRequestControlLock variável UEFI, revisão 2.

Para evitar ataques avançados de memória, a mitigação de segurança do BIOS do sistema existente MemoryOverwriteRequestControl foi aprimorada para suportar o bloqueio para defesa contra novas ameaças. O modelo de ameaça é expandido para incluir o kernel do sistema operacional host como um adversário, portanto, ACPI e UEFI Runtime Services executados no nível de privilégio do kernel não são confiáveis. Semelhante às implementações de Inicialização Segura, o MorLock deve ser implementado em um contexto privilegiado de execução de firmware que não pode ser adulterado pelo kernel do sistema operacional host (por exemplo, Modo de Gerenciamento do Sistema, TrustZone, BMC e assim por diante). A interface é construída com base em serviços variáveis UEFI, que são descritos na Especificação UEFI versão 2.5, Seção 7.2 denominada "Serviços Variáveis".

Essa mitigação, chamada MorLock, deve ser implementada em todos os novos sistemas e não se limita apenas aos sistemas com Trusted Platform Modules. A revisão 2 adiciona um novo recurso, o desbloqueio, para mitigar as preocupações com o desempenho de inicialização, especialmente em sistemas de memória grande.

Em relação ao método de controlo _DSM ACPI para definir o estado do bit MOR (conforme descrito na Seção 6 da Especificação de Mitigação de Ataque de Reposição de Plataforma do Grupo de Trabalho de Clientes de PC, Versão 1.10 (download em PDF)), recomenda-se remover o método _DSM das implementações modernas do BIOS.

No entanto, se um BIOS implementa esse método _DSM, ele deve respeitar o estado de MorLock. Se o MorLock estiver bloqueado, com ou sem uma chave, este método _DSM deve falhar ao alterar MOR e retornar um valor de 1 correspondente a "Falha Geral". Nenhum mecanismo ACPI é definido para desbloquear MorLock revisão 2.

Observe que o Windows não invocou diretamente esse método _DSM desde o Windows 7 e o considera preterido. Alguns BIOS invocam indiretamente esse método _DSM quando o Windows invoca _PTS ACPI como uma implementação do MOR Auto Detection of Clean Shutdown (conforme descrito na Seção 2.3 da PC Client Work Group Platform Reset Attack Mitigation Specification, Versão 1.10 (download em PDF)).

Esta ACPI _PTS implementação do MOR Auto Detection é deficiente em termos de segurança e NÃO deve ser usada.

MemoryOverwriteRequestControlLock

O BIOS que contém a atenuação melhorada cria esta variável UEFI durante o arranque inicial:

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

Designação:MemoryOverwriteRequestControlLock

Atributos: NV+BS+RT

Valor GetVariable no parâmetro Data : 0x0 (desbloqueado); 0x1 (trancado sem chave); 0x2 (bloqueado com chave)

Valor SetVariable no parâmetro Data : 0x0 (desbloqueado); 0x1 (bloqueado)

Bloquear com SetVariable

Em cada inicialização, o BIOS deve inicializar MemoryOverwriteRequestControlLock com um valor de byte único de 0x00 (indicando desbloqueado) antes da fase de seleção do dispositivo de inicialização (BDS) (DRIVER####, SYSPREP####, BOOT####, *RECOVERY*, ...). Para MemoryOverwriteRequestControlLock (e MemoryOverwriteRequestControl), o BIOS deve impedir a exclusão da variável e os atributos devem ser fixados ao NV+BS+RT.

Quando SetVariable for MemoryOverwriteRequestControlLock é chamado pela primeira vez passando um valor válido diferente de zero em Data, o modo de acesso para ambos MemoryOverwriteRequestControlLock e MemoryOverwriteRequestControl é alterado para somente leitura, indicando que estão bloqueados.

As implementações da revisão 1 só aceitam um único byte de 0x00 ou 0x01 para MemoryOverwriteRequestControlLock.

A revisão 2 também aceita um valor de 8 bytes que representa uma chave secreta compartilhada. Se qualquer outro valor for especificado em SetVariable, a chamada falhará com status EFI_INVALID_PARAMETER. Para gerar essa chave, use uma fonte de entropia de alta qualidade, como o Trusted Platform Module ou o gerador de números aleatórios de hardware.

Depois de definir uma chave, tanto o chamador quanto o firmware devem salvar cópias dessa chave em um local protegido por confidencialidade, como SMRAM no IA32/X64 ou um processador de serviço com armazenamento protegido.

Obtendo o estado do sistema

Na Revisão 2, quando as variáveis MemoryOverwriteRequestControlLock e MemoryOverwriteRequestControl estão bloqueadas, as invocações de SetVariable (para essas variáveis) são primeiro verificadas em relação à chave registada usando um algoritmo de tempo constante. Se ambas as chaves estiverem presentes e corresponderem, as variáveis voltarão para um estado desbloqueado. Após essa primeira tentativa ou se nenhuma chave for registrada, as tentativas subsequentes de definir essa variável falharão com EFI_ACCESS_DENIED para evitar ataques de força bruta. Nesse caso, a reinicialização do sistema será a única maneira de desbloquear as variáveis.

O sistema operativo deteta a presença de MemoryOverwriteRequestControlLock e o seu estado chamando GetVariable. O sistema pode então bloquear o valor atual de MemoryOverwriteRequestControl definindo o MemoryOverwriteRequestControlLock valor como 0x1. Como alternativa, ele pode especificar uma chave para habilitar o desbloqueio no futuro depois que os dados secretos tiverem sido limpos com segurança da memória.

Chamar GetVariable para MemoryOverwriteRequestControlLock retornar 0x0, 0x1 ou 0x2 para indicar desbloqueado, bloqueado sem chave ou bloqueado com estados de chave.

A configuração MemoryOverwriteRequestControlLock não confirma o flash (apenas altera o estado de bloqueio interno). Obter a variável retorna o estado interno e nunca expõe a chave.

Exemplo de utilização pelo 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);

Fluxo de implementação do MorLock

Estes fluxogramas mostram o comportamento esperado da sua implementação:

Inicialização

Inicialização de Morlock.

Fluxo SetVariable

Fluxo de programação Morlock.

Fluxo de estado desbloqueado para SetVariable

Morlock desbloqueou o processo.

Fluxo de estado bloqueado para SetVariable

Morlock bloqueou o fluxo.

Fluxo para GetVariable

Morlock GetVariable.

Ver também

requisitos UEFI que se aplicam a todas as edições do Windows em plataformas SoC

Especificação de Mitigação de Ataques de Reinicialização da Plataforma do Grupo de Trabalho de Clientes para PC, Versão 1.10 (PDF para download)

Protegendo o BitLocker contra ataques frios (e outras ameaças)

Um tour além do BIOS com o suporte UEFI TPM2 no EDKII

Proteja credenciais de domínio derivadas com o Credential Guard

UEFI Especificações