Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Os dispositivos com um TPM (Trusted Platform Module) podem confiar no atestado para provar que a integridade da inicialização não foi comprometida, juntamente com o processo de Inicialização Medida para detectar estados de recurso de inicialização antecipada.
Um número crescente de tipos de dispositivo, carregadores de inicialização e ataques de pilha de inicialização exigem que a solução de atestado evolua adequadamente. Um estado atestado de um dispositivo é controlado pela política de atestado usada para verificar o conteúdo na evidência da plataforma.
Este artigo fornece uma visão geral do atestado do TPM e funcionalidades com suporte pelo Atestado do Azure.
Visão geral
O atestado do TPM começa a validar o próprio TPM até o momento em que uma terceira parte confiável possa validar o fluxo de inicialização.
Em geral, o atestado do TPM baseia-se nos seguintes pilares.
Validar a autenticidade do TPM
Valide a autenticidade do TPM com a validação do TPM:
- Cada TPM é fornecido com uma chave assimétrica exclusiva, chamada EK (chave de endosso). Esta chave é queimada pelo fabricante. A parte pública dessa chave é conhecida como EKPub. A chave privada associada é conhecida como EKPriv. Alguns chips TPM também têm um certificado EK emitido pelo fabricante para o EKPub. Este certificado é conhecido como EKCert.
- Uma AC (autoridade de certificação) estabelece a confiança no TPM por meio do EKPub ou do EKCert.
- Um dispositivo prova à AC que a chave para a qual o certificado está sendo solicitado está vinculada criptograficamente ao EKPub e que o TPM é proprietário do EKPriv.
- A AC emite um certificado com uma política de emissão especial para indicar que a chave agora está atestada como protegida por um TPM.
Validar as medidas feitas durante a inicialização
Valide as medidas feitas durante a inicialização usando o Atestado do Azure:
- Como parte da Inicialização Confiável e da Inicialização Medida, cada etapa é validada e medida no TPM. Eventos diferentes são medidos em diferentes plataformas. Para obter mais informações sobre o processo de Inicialização Medida em Windows, consulte Proteger o processo de inicialização do Windows.
- Na inicialização, uma chave de identidade de atestado é gerada. É usado para fornecer prova criptográfica ao serviço de atestado de que o TPM em uso recebeu um certificado após a validação de EK ser realizada.
- As partes confiáveis podem executar um atestado em relação ao Atestado do Azure, que pode ser usado para validar medidas feitas durante o processo de inicialização.
- Uma terceira parte confiável pode, então, contar com a instrução de atestado para acessar recursos ou outras ações.
Conceitualmente, o atestado do TPM pode ser visualizado conforme mostrado no diagrama anterior. A terceira parte confiável aplica o Atestado do Azure para verificar a integridade da plataforma e qualquer violação das promessas. O processo de verificação fornece a confiança para executar cargas de trabalho ou fornecer acesso aos recursos.
Proteção contra ataques de inicialização mal-intencionados
Técnicas de ataque maduras visam infectar a cadeia de inicialização. Um ataque de inicialização pode fornecer ao invasor acesso aos recursos do sistema e permitir que o invasor se oculte do software antimalware. A Inicialização Confiável atua como a primeira ordem de defesa. O uso da Inicialização Confiável e atestado estende a capacidade para partes confiáveis. A maioria dos invasores tenta ignorar a inicialização segura ou carregar um binário indesejado no processo de inicialização.
O atestado remoto permite que as partes confiáveis verifiquem toda a cadeia de inicialização em relação a alguma violação das promessas. Por exemplo, a avaliação de inicialização segura pelo serviço de atestado valida os valores das variáveis seguras medidas pela UEFI.
A instrumentação de inicialização medida garante que as medidas vinculadas criptograficamente não possam ser alteradas após serem feitas e que apenas um componente confiável pode fazer a medição. Por esta razão, validar as variáveis seguras é suficiente para garantir a habilitação.
O Atestado do Azure assina o relatório para garantir que a integridade do atestado também será mantida para proteger contra ataques man-in-the-middle.
Uma política simples pode ser usada:
version=1.0;
authorizationrules {
=> permit();
};
issuancerules
{
[type=="aikValidated", value==true] &&
[type=="secureBootEnabled", value==true] => issue(type="PlatformAttested", value=true);
};
Às vezes, não é suficiente verificar apenas um componente na inicialização. Verificar recursos complementares, como integridade de código ou HVCI (integridade de código protegido por hipervisor) e Início Seguro do System Guard, adiciona ao perfil de proteção de um dispositivo. Você também precisa da capacidade de emparelhar na inicialização para que você possa avaliar quaisquer violações e ter confiança sobre a plataforma.
O exemplo a seguir aproveita a política versão 1.2 para verificar detalhes sobre inicialização segura, HVCI e o Início Seguro do System Guard. Ele também verifica se um driver indesejado (malicious.sys) não está carregado durante a inicialização:
version=1.2;
authorizationrules {
=> permit();
};
issuancerules
{
// Verify if secure boot is enabled
c:[type == "events", issuer=="AttestationService"] => add(type = "efiConfigVariables", value = JmesPath(c.value, "Events[?EventTypeString == 'EV_EFI_VARIABLE_DRIVER_CONFIG' && ProcessedData.VariableGuid == '8BE4DF61-93CA-11D2-AA0D-00E098032B8C']"));
c:[type=="efiConfigVariables", issuer=="AttestationPolicy"]=> add(type = "secureBootEnabled", value = JsonToClaimValue(JmesPath(c.value, "[?ProcessedData.UnicodeName == 'SecureBoot'] | length(@) == `1` && @[0].ProcessedData.VariableData == 'AQ'")));
![type=="secureBootEnabled", issuer=="AttestationPolicy"] => add(type="secureBootEnabled", value=false);
// HVCI
c:[type=="events", issuer=="AttestationService"] => add(type="srtmDrtmEventPcr", value=JmesPath(c.value, "Events[? EventTypeString == 'EV_EVENT_TAG' && (PcrIndex == `12` || PcrIndex == `19`)].ProcessedData.EVENT_TRUSTBOUNDARY"));
c:[type=="srtmDrtmEventPcr", issuer=="AttestationPolicy"] => add(type="hvciEnabledSet", value=JsonToClaimValue(JmesPath(c.value, "[*].EVENT_VBS_HVCI_POLICY | @[?String == 'HypervisorEnforcedCodeIntegrityEnable'].Value")));
c:[type=="hvciEnabledSet", issuer=="AttestationPolicy"] => issue(type="hvciEnabled", value=ContainsOnlyValue(c.value, 1));
![type=="hvciEnabled", issuer=="AttestationPolicy"] => issue(type="hvciEnabled", value=false);
// Validating unwanted(malicious.sys) driver is not loaded
c:[type=="events", issuer=="AttestationService"] => add(type="boolProperties", value=JmesPath(c.value, "Events[? EventTypeString == 'EV_EVENT_TAG' && (PcrIndex == `12` || PcrIndex == `13` || PcrIndex == `19` || PcrIndex == `20`)].ProcessedData.EVENT_TRUSTBOUNDARY"));
c:[type=="boolProperties", issuer=="AttestationPolicy"] => issue(type="MaliciousDriverLoaded", value=JsonToClaimValue(JmesPath(c.value, "[*].EVENT_LOADEDMODULE_AGGREGATION[] | [? EVENT_IMAGEVALIDATED == true && (equals_ignore_case(EVENT_FILEPATH, '\\windows\\system32\\drivers\\malicious.sys') || equals_ignore_case(EVENT_FILEPATH, '\\windows\\system32\\drivers\\wd\\malicious.sys'))] | @ != null ")));
![type=="MaliciousDriverLoaded", issuer=="AttestationPolicy"] => issue(type="MaliciousDriverLoaded", value=false);
};
Estender a proteção contra ataques de inicialização mal-intencionados por meio da IMA (Arquitetura de Medição de Integridade) no Linux
Os sistemas Linux seguem um processo de inicialização semelhante ao Windows e, com o atestado de TPM, o perfil de proteção pode ser estendido para além da inicialização no kernel, também usando a IMA (Arquitetura de Medição de Integridade). O subsistema IMA foi projetado para detectar se os arquivos foram alterados de maneira acidental ou maliciosa, tanto remotamente quanto localmente. Ele mantém uma lista de medidas de runtime e, se ancorado em um TPM (Trusted Platform Module) de hardware, um valor de integridade agregado sobre essa lista fornecerá o benefício da resiliência em ataques de software. Aprimoramentos recentes no subsistema IMA também permitem que atributos não baseados em arquivo sejam medidos e atestados remotamente. O atestado do Azure dá suporte a medições não baseadas em arquivo a serem atestadas remotamente para fornecer uma visão holística da integridade do sistema.
Habilitar a IMA com a seguinte política de IMA habilitará a medição de atributos que não são de arquivo e ainda habilitará o atestado de integridade de arquivo local.
Usando a política de Atestado a seguir, agora é possível validar o secureboot, a assinatura do kernel, a versão do kernel, o cmdline do kernel passado por grub e outros atributos de segurança de chave com suporte da IMA.
version = 1.2;
configurationrules
{
};
authorizationrules
{
[type == "aikValidated", value==true]
=> permit();
};
issuancerules {
// Retrieve all EFI Boot variables with event = 'EV_EFI_VARIABLE_BOOT'
c:[type == "events", issuer=="AttestationService"] => add(type ="efiBootVariables", value = JmesPath(c.value, "Events[?EventTypeString == 'EV_EFI_VARIABLE_BOOT']"));
// Retrieve all EFI Driver Config variables with event = 'EV_EFI_VARIABLE_DRIVER_CONFIG'
c:[type == "events", issuer=="AttestationService"] => add(type ="efiConfigVariables", value = JmesPath(c.value, "Events[?EventTypeString == 'EV_EFI_VARIABLE_DRIVER_CONFIG']"));
// Grab all IMA events
c:[type=="events", issuer=="AttestationService"] => add(type="imaMeasurementEvents", value=JmesPath(c.value, "Events[?EventTypeString == 'IMA_MEASUREMENT_EVENT']"));
// Look for "Boot Order" from EFI Boot Data
c:[type == "efiBootVariables", issuer=="AttestationPolicy"] => add(type = "bootOrderFound", value = JmesPath(c.value, "[?ProcessedData.UnicodeName == 'BootOrder'] | length(@) == `1` && @[0].PcrIndex == `1` && @[0].ProcessedData.VariableData"));
c:[type=="bootOrderFound", issuer=="AttestationPolicy"] => issue(type="bootOrder", value=JsonToClaimValue(c.value));
![type=="bootOrderFound", issuer=="AttestationPolicy"] => issue(type="bootOrder", value=0);
// Look for "Secure Boot" from EFI Driver Configuration Data
c:[type == "efiConfigVariables", issuer=="AttestationPolicy"] => issue(type = "secureBootEnabled", value = JsonToClaimValue(JmesPath(c.value, "[?ProcessedData.UnicodeName == 'SecureBoot'] | length(@) == `1` && @[0].PcrIndex == `7` && @[0].ProcessedData.VariableData == 'AQ'")));
![type=="secureBootEnabled", issuer=="AttestationPolicy"] => issue(type="secureBootEnabled", value=false);
// Look for "Platform Key" from EFI Boot Data
c:[type == "efiConfigVariables", issuer=="AttestationPolicy"] => add(type = "platformKeyFound", value = JmesPath(c.value, "[?ProcessedData.UnicodeName == 'PK'] | length(@) == `1` && @[0].PcrIndex == `7` && @[0].ProcessedData.VariableData"));
c:[type=="platformKeyFound", issuer=="AttestationPolicy"] => issue(type="platformKey", value=JsonToClaimValue(c.value));
![type=="platformKeyFound", issuer=="AttestationPolicy"] => issue(type="platformKey", value=0);
// Look for "Key Exchange Key" from EFI Driver Configuration Data
c:[type == "efiConfigVariables", issuer=="AttestationPolicy"] => add(type = "keyExchangeKeyFound", value = JmesPath(c.value, "[?ProcessedData.UnicodeName == 'KEK'] | length(@) == `1` && @[0].PcrIndex == `7` && @[0].ProcessedData.VariableData"));
c:[type=="keyExchangeKeyFound", issuer=="AttestationPolicy"] => issue(type="keyExchangeKey", value=JsonToClaimValue(c.value));
![type=="keyExchangeKeyFound", issuer=="AttestationPolicy"] => issue(type="keyExchangeKey", value=0);
// Look for "Key Database" from EFI Driver Configuration Data
c:[type == "efiConfigVariables", issuer=="AttestationPolicy"] => add(type = "keyDatabaseFound", value = JmesPath(c.value, "[?ProcessedData.UnicodeName == 'db'] | length(@) == `1` && @[0].PcrIndex == `7` && @[0].ProcessedData.VariableData"));
c:[type=="keyDatabaseFound", issuer=="AttestationPolicy"] => issue(type="keyDatabase", value=JsonToClaimValue(c.value));
![type=="keyDatabaseFound", issuer=="AttestationPolicy"] => issue(type="keyDatabase", value=0);
// Look for "Forbidden Signatures" from EFI Driver Configuration Data
c:[type == "efiConfigVariables", issuer=="AttestationPolicy"] => add(type = "forbiddenSignaturesFound", value = JmesPath(c.value, "[?ProcessedData.UnicodeName == 'dbx'] | length(@) == `1` && @[0].PcrIndex == `7` && @[0].ProcessedData.VariableData"));
c:[type=="forbiddenSignaturesFound", issuer=="AttestationPolicy"] => issue(type="forbiddenSignatures", value=JsonToClaimValue(c.value));
![type=="forbiddenSignaturesFound", issuer=="AttestationPolicy"] => issue(type="forbiddenSignatures", value=0);
// Look for "Kernel Version" in IMA Measurement events
c:[type=="imaMeasurementEvents", issuer=="AttestationPolicy"] => add(type="kernelVersionsFound", value=JmesPath(c.value, "[].ProcessedData.KernelVersion"));
c:[type=="kernelVersionsFound", issuer=="AttestationPolicy"] => issue(type="kernelVersions", value=JsonToClaimValue(c.value));
![type=="kernelVersionsFound", issuer=="AttestationPolicy"] => issue(type="kernelVersions", value=0);
// Look for "Built-In Trusted Keys" in IMA Measurement events
c:[type=="imaMeasurementEvents", issuer=="AttestationPolicy"] => add(type="builtintrustedkeysFound", value=JmesPath(c.value, "[? ProcessedData.Keyring == '.builtin_trusted_keys'].ProcessedData.CertificateSubject"));
c:[type=="builtintrustedkeysFound", issuer=="AttestationPolicy"] => issue(type="builtintrustedkeys", value=JsonToClaimValue(c.value));
![type=="builtintrustedkeysFound", issuer=="AttestationPolicy"] => issue(type="builtintrustedkeys", value=0);
};
Observação: o suporte para medições não baseadas em arquivo só está disponível a partir da versão do kernel do Linux: 5.15
Suporte ao atestado de Chave de TPM
Vários aplicativos dependem do gerenciamento de credenciais fundamentais de chaves e certificados para proteções contra roubo de credenciais, sendo que uma das principais maneiras de garantir a segurança de credenciais é a dependência de provedores de armazenamento de chaves que fornecem segurança adicional contra malware e ataques. O Windows implementa vários provedores criptográficos que podem ser baseados em software ou hardware.
Os dois mais importantes são:
Provedor de Armazenamento de Chaves de Software da Microsoft: provedor Standard, que armazena chaves baseadas em software e dá suporte a CNG (Próxima Geração de Criptografia)
Provedor de Criptografia da Plataforma Microsoft: provedor baseado em hardware que armazena chaves em um TPM (Trusted Platform Module) e também dá suporte a CNG
Sempre que um provedor de Armazenamento é usado, ele geralmente serve para criar um par de chaves pub/priv que é encadeado a uma raiz de confiança. Na criação, mais propriedades também podem ser usadas para habilitar determinados aspectos do armazenamento de chaves, exportabilidade etc. O atestado de chave, nesse contexto, é a capacidade técnica de provar a uma entidade de resposta que uma chave privada foi gerada internamente e é gerenciada internamente em uma forma não exportável. Esse atestado combinado com outras informações pode ajudar a proteger contra roubo de credenciais e tipo de ataque de reprodução.
Os TPMs também fornecem a capacidade de atestar que as chaves estão residentes em um TPM, aumentando a garantia de segurança, com suporte de não exportabilidade, anti-hammering e isolamento de chaves. Um caso de uso comum é para aplicativos que emitem certificado de assinatura digital para chaves de assinante, verificando se a chave de assinatura privada dos assinantes é gerada e gerenciada em um TPM aprovado. Pode-se facilmente atestar o fato de que as chaves são residentes em um TPM válido com sinalizadores Nonexportability apropriados usando uma política como abaixo.
version=1.2;
authorizationrules
{
=> permit();
};
issuancerules
{
// Key Attest Policy
// -- Validating key types
c:[type=="x-ms-tpm-request-key", issuer=="AttestationService"] => add(type="requestKeyType", value=JsonToClaimValue(JmesPath(c.value, "jwk.kty")));
c:[type=="x-ms-tpm-other-keys", issuer=="AttestationService"] => add(type="otherKeysTypes", value=JsonToClaimValue(JmesPath(c.value, "[*].jwk.kty")));
c:[type=="requestKeyType", issuer=="AttestationPolicy", value=="RSA"] => issue(type="requestKeyType", value="RSA");
c:[type=="otherKeysTypes", issuer=="AttestationPolicy", value=="RSA"] => issue(type="otherKeysTypes", value="RSA");
// -- Validating tpm_quote attributes
c:[type=="x-ms-tpm-request-key", issuer=="AttestationService"] => add(type="requestKeyQuote", value=JmesPath(c.value, "info.tpm_quote"));
c:[type=="requestKeyQuote", issuer=="AttestationPolicy"] => add(type="requestKeyQuoteHashAlg", value=JsonToClaimValue(JmesPath(c.value, "hash_alg")));
c:[type=="requestKeyQuoteHashAlg", issuer=="AttestationPolicy", value=="sha-256"] => issue(type="requestKeyQuoteHashAlg", value="sha-256");
// -- Validating tpm_certify attributes
c:[type=="x-ms-tpm-request-key", issuer=="AttestationService"] => add(type="requestKeyCertify", value=JmesPath(c.value, "info.tpm_certify"));
c:[type=="requestKeyCertify", issuer=="AttestationPolicy"] => add(type="requestKeyCertifyNameAlg", value=JsonToClaimValue(JmesPath(c.value, "name_alg")));
c:[type=="requestKeyCertifyNameAlg", issuer=="AttestationPolicy", value==11] => issue(type="requestKeyCertifyNameAlg", value=11);
c:[type=="requestKeyCertify", issuer=="AttestationPolicy"] => add(type="requestKeyCertifyObjAttr", value=JsonToClaimValue(JmesPath(c.value, "obj_attr")));
c:[type=="requestKeyCertifyObjAttr", issuer=="AttestationPolicy", value==50] => issue(type="requestKeyCertifyObjAttr", value=50);
c:[type=="requestKeyCertify", issuer=="AttestationPolicy"] => add(type="requestKeyCertifyAuthPolicy", value=JsonToClaimValue(JmesPath(c.value, "auth_policy")));
c:[type=="requestKeyCertifyAuthPolicy", issuer=="AttestationPolicy", value=="AQIDBA"] => issue(type="requestKeyCertifyAuthPolicy", value="AQIDBA");
c:[type=="x-ms-tpm-other-keys", issuer=="AttestationService"] => add(type="otherKeysCertify", value=JmesPath(c.value, "[*].info.tpm_certify"));
c:[type=="otherKeysCertify", issuer=="AttestationPolicy"] => add(type="otherKeysCertifyNameAlgs", value=JsonToClaimValue(JmesPath(c.value, "[*].name_alg")));
c:[type=="otherKeysCertifyNameAlgs", issuer=="AttestationPolicy", value==11] => issue(type="otherKeysCertifyNameAlgs", value=11);
c:[type=="otherKeysCertify", issuer=="AttestationPolicy"] => add(type="otherKeysCertifyObjAttr", value=JsonToClaimValue(JmesPath(c.value, "[*].obj_attr")));
c:[type=="otherKeysCertifyObjAttr", issuer=="AttestationPolicy", value==50] => issue(type="otherKeysCertifyObjAttr", value=50);
c:[type=="otherKeysCertify", issuer=="AttestationPolicy"] => add(type="otherKeysCertifyAuthPolicy", value=JsonToClaimValue(JmesPath(c.value, "[*].auth_policy")));
c:[type=="otherKeysCertifyAuthPolicy", issuer=="AttestationPolicy", value=="AQIDBA"] => issue(type="otherKeysCertifyAuthPolicy", value="AQIDBA");
};