Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Los dispositivos con un Módulo de plataforma segura (TPM) pueden confiar en la atestación para comprobar que la integridad del arranque no se ve comprometida, además de utilizar el proceso de arranque medido para detectar los estados de las características durante la primera fase de arranque.
Un número creciente de tipos de dispositivos, cargadores de arranque y ataques de pila de arranque precisan una solución de atestación para evolucionar adecuadamente. Un estado atestado de un dispositivo está controlado por la directiva de atestación que se usa para comprobar el contenido de la evidencia de la plataforma.
En este artículo se proporciona información general sobre la atestación y las funcionalidades de TPM compatibles con Azure Attestation.
Información general
La atestación de TPM comienza por validar el propio TPM hasta el punto en el que un usuario de confianza puede validar el flujo de arranque.
En general, la atestación de TPM se basa en los siguientes pilares.
Validación de la autenticidad del TPM
Valide la autenticidad del TPM mediante la validación del TPM:
- Cada TPM se suministra con una clave asimétrica única, denominada clave de aprobación (EK). Esta clave se graba por el fabricante. La parte pública de esta clave se conoce como EKPub. La clave privada asociada se conoce como EKPriv. Algunos chips TPM también tienen un certificado de EK emitido por el fabricante para la EKPub. Este certificado se conoce como EKCert.
- Una entidad de certificación (CA) establece la confianza en el TPM a través de la EKPub o el EKCert.
- Un dispositivo demuestra a la CA que la clave para la que se solicita el certificado está enlazada criptográficamente a la EKPub y que el TPM posee la EKPriv.
- La entidad de certificación emite un certificado con una directiva de emisión especial para indicar que la clave ahora está atestada para como protegida por un TPM.
Validación de las medidas realizadas durante el arranque
Valide las medidas realizadas durante el arranque mediante el servicio Azure Attestation:
- Como parte de los arranques de confianza y medido, cada paso se valida y mide en el TPM. Los diferentes eventos se miden para distintas plataformas. Para más información sobre el proceso de arranque medido en Windows, consulte Protección del proceso de arranque de Windows.
- En el arranque, se genera una clave de identidad de atestación. Se usa para proporcionar una prueba criptográfica al servicio de atestación que se emitió un certificado del TPM en uso después de que se realizase una validación EK.
- Los usuarios de confianza pueden realizar una atestación con Azure Attestation, que se puede usar para validar las mediciones realizadas durante el proceso de arranque.
- Después, un usuario de confianza puede basarse en la instrucción de atestación para permitir el acceso a los recursos u otras acciones.
Conceptualmente, la atestación de TPM se puede visualizar como se muestra en el diagrama anterior. El usuario de confianza aplica Azure Attestation para comprobar la integridad de la plataforma y cualquier infracción de promesas. El proceso de comprobación proporciona confianza para ejecutar cargas de trabajo o proporcionar acceso a los recursos.
Protección frente a ataques de arranque maliciosos
Las técnicas de ataque desarrolladas tienen como objetivo infectar la cadena de arranque. Un ataque de arranque puede proporcionar al atacante acceso a los recursos del sistema y permitir que el atacante se oculte del software antimalware. El arranque de confianza actúa como primer orden de defensa. El uso del arranque de confianza y la atestación amplían la capacidad de los usuarios de confianza. La mayoría de los atacantes intentan eludir el arranque seguro o cargar un binario no deseado en el proceso de arranque.
La atestación remota permite a los usuarios de confianza comprobar toda la cadena de arranque por si hay alguna infracción de promesas. Por ejemplo, la evaluación de arranque seguro mediante el servicio de atestación valida los valores de las variables seguras medidas por UEFI.
La instrumentación del arranque medido garantiza que las medidas enlazadas criptográficamente no se puedan cambiar una vez realizadas y que solo un componente de confianza pueda realizar la medición. Por este motivo, validar las variables seguras es suficiente para garantizar la habilitación.
Azure Attestation firma el informe para garantizar que también se mantiene la integridad de la atestación para la protección contra ataques de tipo "Man in the middle".
Se puede usar una directiva simple:
version=1.0;
authorizationrules {
=> permit();
};
issuancerules
{
[type=="aikValidated", value==true] &&
[type=="secureBootEnabled", value==true] => issue(type="PlatformAttested", value=true);
};
A veces, no es suficiente comprobar solo un componente en el arranque. La comprobación de características complementarias como la integridad de código o la integridad de código protegida por hipervisor (HVCI) y el inicio seguro de Protección del sistema se agregan al perfil de protección de un dispositivo. También necesita la capacidad mirar el arranque para poder evaluar cualquier infracción y estar seguro de la plataforma.
En el ejemplo siguiente se aprovecha la versión 1.2 de la directiva para comprobar los detalles sobre el arranque seguro, HVCI y el inicio seguro de Protección del sistema. También comprueba que un controlador no deseado (malicious.sys) no se carga durante el arranque:
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);
};
Ampliación de la protección frente a ataques de arranque malintencionados mediante la arquitectura de medición de integridad (IMA) en Linux
Los sistemas Linux siguen un proceso de arranque similar a Windows y, con la atestación de TPM, el perfil de protección se puede ampliar más allá del arranque en el kernel y utilizar la arquitectura de medición de integridad (IMA). El subsistema IMA se diseñó para detectar si los archivos se modificaban accidental o malintencionadamente, de forma remota y local, mantiene una lista de medidas en el entorno de ejecución y, si está anclado en un módulo de plataforma segura de hardware (TPM), un valor de integridad agregado en esta lista proporciona la ventaja de resistencia frente a ataques de software. Las mejoras recientes del subsistema IMA también permiten medir y atestiguar de forma remota atributos no basados en archivos. La atestación de Azure admite que las mediciones no basadas en archivos se atestigüen de forma remota para proporcionar una vista holística de la integridad del sistema.
Habilitar IMA con la siguiente directiva de IMA habilitará la medición de atributos que no están basados en archivos, al tiempo que se habilita la atestación de la integridad de los archivos locales.
Con la siguiente directiva de atestación, ahora puede validar el arranque seguro, la firma del kernel, la versión del kernel, cmdline del kernel pasado por grub y otros atributos de seguridad clave admitidos por 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);
};
Nota: La compatibilidad con medidas no basadas en archivos solo está disponible desde la versión del kernel de Linux: 5.15
Compatibilidad con la atestación de clave de TPM
Muchas aplicaciones se basan en la administración de credenciales fundamentales de claves y certificados para la protección frente al robo de credenciales, y una de las principales formas de garantizar la seguridad de estas es la confianza en los proveedores de almacenamiento de claves que proporcionan seguridad adicional contra malware y ataques. Windows implementa varios proveedores criptográficos que pueden estar basados en software o hardware.
Los dos más importantes son:
Proveedor de almacenamiento de claves de software de Microsoft: proveedor estándar, que almacena claves basadas en software y admite CNG (Crypto-Next Generation)
Proveedor criptográfico de plataforma de Microsoft: basado en un hardware que almacena claves en un TPM (módulo de plataforma segura) y también admite CNG.
Siempre que se usa un proveedor de almacenamiento, normalmente es para crear un par de claves pub/priv que está encadenado a una raíz de confianza. En la creación, también se pueden usar más propiedades para habilitar determinados aspectos del almacenamiento de claves, la exportabilidad, etc. La atestación de claves en este contexto es la capacidad técnica de demostrar a una entidad de respuesta que dentro se generó una clave privada y que esta se administra dentro y en un formato no exportable. Esta atestación, juntó con otra información, puede ayudar a proteger contra el robo de credenciales y el tipo de ataque de reproducción.
Los TPM también proporcionan la posibilidad de atestiguar que las claves residen en un TPM, lo que permite una mayor garantía de seguridad, respaldada por la no exportabilidad, la protección contra ataques por repetición y el aislamiento de las claves. Un caso de uso común es para las aplicaciones que emiten un certificado de firma digital para las claves de suscriptor y que comprueban que la clave de firma privada de los suscriptores se genera y administra en un TPM aprobado. Una puede atestiguar fácilmente el hecho de que las claves residen en un TPM válido con marcas de No exportabilidad adecuadas mediante una directiva como se indica a continuación.
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");
};