Implementação de MOR segura
Resumo
- Comportamento de MorLock, revisão 2
Última atualização
- Agosto de 2020
Aplica-se a
Windows 10
Fornecedores de OEMs e BIOS que desejam dar suporte ao recurso credential Guard de Windows 10.
Especificações oficiais
Leitura recomendada
Postagem no blog: Protegendo o BitLocker contra ataques frios (e outras ameaças)
Whitepaper: um tour além do BIOS com o suporte do UEFI TPM2 no EDKII
Proteger as credenciais de domínio derivadas com o Credential Guard
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 é aprimorada para dar suporte ao bloqueio para se defender contra novas ameaças. O modelo de ameaça é expandido para incluir o kernel do sistema operacional host como um adversário, portanto, os Serviços de Runtime do ACPI e UEFI em execução 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 de execução de firmware privilegiado 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 é criada com base em serviços de variáveis UEFI, que são descritos na Especificação uefi versão 2.5, Seção 7.2 chamada "Serviços variáveis".
Essa mitigação, chamada MorLock, deve ser implementada em todos os novos sistemas e não apenas em sistemas com módulos de plataforma confiáveis. A revisão 2 adiciona uma nova funcionalidade, desbloqueio, para atenuar as preocupações de desempenho de inicialização, especialmente em sistemas de memória grandes.
Em relação ao método de controle de _DSM ACPI para definir o estado do bit MOR (conforme descrito na Seção 6 da Especificação de Mitigação de Ataque de Redefinição de Plataforma de Redefinição de Grupo de Trabalho do Pc, Versão 1.10 (download em PDF), recomendamos remover esse método _DSM das implementações modernas do BIOS.
No entanto, se um BIOS implementar esse método _DSM, ele deverá respeitar o estado de MorLock. Se o MorLock estiver bloqueado, com ou sem uma chave, esse método _DSM deverá falhar ao alterar MOR e retornar um valor de 1 correspondente a "Falha Geral". Nenhum mecanismo de ACPI é definido para desbloquear a revisão 2 do MorLock.
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 o ACPI _PTS como uma implementação da Detecção Automática mor de desligamento limpo (conforme descrito na Seção 2.3 da Especificação de Mitigação de Ataque de Redefinição de Plataforma de Redefinição de Plataforma de Trabalho do Pc, Versão 1.10 (download em PDF)).
Essa ACPI _PTS implementação da Detecção Automática de MOR é deficiente de segurança e NÃO deve ser usada.
MemoryOverwriteRequestControlLock
O BIOS que contém a mitigação aprimorada cria essa variável UEFI durante a inicialização antecipada:
VendorGuid:{BB983CCF-151D-40E1-A07B-4A17BE168292}
Nome:MemoryOverwriteRequestControlLock
Atributos: NV+BS+RT
Valor GetVariable no parâmetro Data : 0x0 (desbloqueado); 0x1 (bloqueado sem chave); 0x2 (bloqueado com chave)
Valor SetVariable no parâmetro Data : 0x0 (desbloqueado); 0x1 (bloqueado)
Bloqueio com SetVariable
Em cada inicialização, o BIOS deve inicializar MemoryOverwriteRequestControlLock
para 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 em NV+BS+RT.
Quando SetVariable for MemoryOverwriteRequestControlLock
chamado pela primeira vez passando um valor não zero válido em Dados, o modo de acesso para e MemoryOverwriteRequestControlLock
MemoryOverwriteRequestControl
é alterado para somente leitura, indicando que eles estão bloqueados.
As implementações de revisão 1 aceitam apenas 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úmero aleatório de hardware.
Depois de definir uma chave, o chamador e o firmware devem salvar cópias dessa chave em um local protegido por confidencialidade, como SMRAM em IA32/X64 ou um processador de serviço com armazenamento protegido.
Obtendo o estado do sistema
Na Revisão 2, quando as MemoryOverwriteRequestControlLock
variáveis e MemoryOverwriteRequestControl
são bloqueadas, as invocações de SetVariable (para essas variáveis) são verificadas pela primeira vez na chave registrada 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 operacional detecta a presença de MemoryOverwriteRequestControlLock
e seu estado chamando GetVariable. Em seguida, o sistema pode 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 forem limpos com segurança da memória.
Chamar GetVariable para MemoryOverwriteRequestControlLock
retorna 0x0, 0x1 ou 0x2 para indicar desbloqueado, bloqueado sem chave ou bloqueado com estados de chave.
A configuração MemoryOverwriteRequestControlLock
não se confirma como flash (apenas altera o estado de bloqueio interno). Obter a variável retorna o estado interno e nunca expõe a chave.
Exemplo de uso pelo sistema operacional:
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
Esses fluxogramas mostram o comportamento esperado da implementação:
Inicialização
Fluxo SetVariable
Fluxo de estado desbloqueado para SetVariable
Fluxo de estado bloqueado para SetVariable
Fluxo para GetVariable
Confira também
Requisitos de UEFI que se aplicam a todas as edições do Windows em plataformas SoC
Protegendo o BitLocker contra ataques frios (e outras ameaças)
Um tour além do BIOS com o suporte do UEFI TPM2 no EDKII
Proteger as credenciais de domínio derivadas com o Credential Guard
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de