Udostępnij za pośrednictwem


Zaświadczenie modułu Trusted Platform Module

Urządzenia z modułem TPM (Trusted Platform Module) mogą polegać na zaświadczeniu, aby udowodnić, że integralność rozruchu nie zostanie naruszona wraz z użyciem procesu mierzonego rozruchu w celu wykrywania stanów funkcji wczesnego rozruchu.

Rosnąca liczba typów urządzeń, modułów ładujących i ataków stosu rozruchowego wymaga odpowiedniego rozwiązania zaświadczania. Zaświadczony stan urządzenia jest napędzany przez zasady zaświadczania używane do weryfikowania zawartości na dowodach platformy.

Ten artykuł zawiera omówienie zaświadczania modułu TPM i możliwości obsługiwanych przez zaświadczenie platformy Azure.

Omówienie

Zaświadczanie modułu TPM rozpoczyna się od weryfikacji samego modułu TPM aż do punktu, w którym jednostka uzależniona może zweryfikować przepływ rozruchu.

Ogólnie rzecz biorąc, zaświadczenie modułu TPM opiera się na następujących filarach.

Weryfikowanie autentyczności modułu TPM

Zweryfikuj autentyczność modułu TPM, weryfikując moduł TPM:

  • Każdy moduł TPM jest dostarczany z unikatowym kluczem asymetrycznym nazywanym kluczem poręczenia (EK). Ten klucz jest spalony przez producenta. Publiczna część tego klucza jest znana jako EKPub. Skojarzony klucz prywatny jest znany jako EKPriv. Niektóre układy TPM mają również certyfikat EK wystawiony przez producenta dla EKPub. Ten certyfikat jest znany jako EKCert.
  • Urząd certyfikacji ustanawia zaufanie do modułu TPM za pośrednictwem EKPub lub EKCert.
  • Urządzenie potwierdza urząd certyfikacji, że klucz, dla którego żądano certyfikatu, jest kryptograficznie powiązany z EKPub i że moduł TPM jest właścicielem EKPriv.
  • Urząd certyfikacji wystawia certyfikat ze specjalnymi zasadami wystawiania, aby określić, że klucz jest teraz testowany jako chroniony przez moduł TPM.

Weryfikowanie pomiarów wykonanych podczas rozruchu

Zweryfikuj pomiary wykonane podczas rozruchu przy użyciu zaświadczania platformy Azure:

  • W ramach zaufanego rozruchu i mierzonego rozruchu każdy krok jest weryfikowany i mierzony w module TPM. Różne zdarzenia są mierzone dla różnych platform. Aby uzyskać więcej informacji na temat mierzonego procesu rozruchu w systemie Windows, zobacz Zabezpieczanie procesu rozruchu systemu Windows.
  • Podczas rozruchu jest generowany klucz tożsamości zaświadczania. Służy do dostarczania dowodu kryptograficznego do usługi zaświadczania, że moduł TPM w użyciu został wystawiony certyfikat po przeprowadzeniu weryfikacji klucza EK.
  • Jednostki uzależnione mogą wykonywać zaświadczanie względem zaświadczania platformy Azure, które może służyć do weryfikowania pomiarów wykonanych podczas procesu rozruchu.
  • Jednostka uzależniona może następnie polegać na instrukcji zaświadczania w celu uzyskania dostępu do zasobów lub innych akcji.

Diagram przedstawiający przepływ zaświadczania urządzenia koncepcyjnego.

Koncepcyjnie zaświadczanie modułu TPM można wizualizować, jak pokazano na powyższym diagramie. Jednostka uzależniona stosuje zaświadczanie platformy Azure w celu zweryfikowania integralności platformy i wszelkich naruszeń obietnic. Proces weryfikacji zapewnia pewność uruchamiania obciążeń lub zapewniania dostępu do zasobów.

Ochrona przed złośliwymi atakami rozruchowymi

Dojrzałe techniki ataku mają na celu zainfekowanie łańcucha rozruchu. Atak rozruchowy może zapewnić atakującemu dostęp do zasobów systemowych i umożliwić atakującemu ukrycie się przed oprogramowaniem chroniącym przed złośliwym kodem. Zaufany rozruch działa jako pierwszy porządek obrony. Użycie zaufanego rozruchu i zaświadczania rozszerza możliwości jednostek uzależnionych. Większość osób atakujących próbuje pominąć bezpieczny rozruch lub załadować niechciany plik binarny w procesie rozruchu.

Zdalne zaświadczanie umożliwia stronom uzależnionym zweryfikowanie całego łańcucha rozruchu pod kątem naruszenia obietnic. Na przykład bezpieczna ocena rozruchu przez usługę zaświadczania weryfikuje wartości zmiennych bezpiecznych mierzonych przez interfejs UEFI.

Instrumentacja mierzonego rozruchu gwarantuje, że pomiary powiązane kryptograficznie nie mogą zostać zmienione po ich utworzeniu i że tylko zaufany składnik może dokonać pomiaru. Z tego powodu weryfikowanie bezpiecznych zmiennych jest wystarczające, aby zapewnić włączenie.

Zaświadczenie platformy Azure podpisuje raport, aby zapewnić integralność zaświadczania również w celu ochrony przed atakami typu man-in-the-middle.

Można użyć prostych zasad:

version=1.0;

authorizationrules { 
    => permit();
};


issuancerules
{
[type=="aikValidated", value==true] && 
[type=="secureBootEnabled", value==true] => issue(type="PlatformAttested", value=true);
};

Czasami nie wystarczy zweryfikować tylko jeden składnik w rozruchu. Weryfikowanie uzupełniających funkcji, takich jak integralność kodu lub integralność kodu chronionego przez funkcję hypervisor (HVCI) i funkcja Bezpiecznego uruchamiania funkcji System Guard dodaje do profilu ochrony urządzenia. Potrzebujesz również możliwości komunikacji równorzędnej z rozruchem, aby można było ocenić wszelkie naruszenia i mieć pewność co do platformy.

Poniższy przykład korzysta z zasad w wersji 1.2, aby zweryfikować szczegóły bezpiecznego rozruchu, HVCI i bezpiecznego uruchamiania funkcji System Guard. Sprawdza również, czy niechciany sterownik (malicious.sys) nie jest ładowany podczas rozruchu:

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

};

Rozszerzanie ochrony przed złośliwymi atakami rozruchowymi za pośrednictwem architektury pomiaru integralności (IMA) w systemie Linux

Systemy Linux są zgodne z podobnym procesem rozruchu do systemu Windows, a zaświadczanie modułu TPM umożliwia rozszerzenie profilu ochrony do poza rozruchem w jądrze, a także przy użyciu architektury pomiaru integralności (IMA). Podsystem IMA został zaprojektowany pod kątem wykrywania, czy pliki zostały przypadkowo lub złośliwie zmienione, zarówno zdalnie, jak i lokalnie, utrzymuje listę pomiarów środowiska uruchomieniowego i, jeśli są zakotwiczone w sprzętowym module Trusted Platform Module (TPM), zagregowana wartość integralności na tej liście zapewnia odporność na ataki oprogramowania. Najnowsze ulepszenia podsystemu IMA umożliwiają również pomiar i zdalne testowanie atrybutów nienależących do plików. Zaświadczanie platformy Azure obsługuje pomiary nie oparte na plikach, które mają być testowane zdalnie w celu zapewnienia całościowego widoku integralności systemu.

Włączenie funkcji IMA przy użyciu następujących zasad ima umożliwi pomiar atrybutów innych niż pliki, jednocześnie włączając lokalne zaświadczanie integralności plików.

Korzystając z poniższych zasad zaświadczania, można teraz zweryfikować bezpieczny rozruch, podpis jądra, wersję jądra, wiersz wiersza jądra przekazany przez grub i inne kluczowe atrybuty zabezpieczeń obsługiwane przez 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);
};

Uwaga: Obsługa pomiarów niezwiązanych z plikami jest dostępna tylko w wersji jądra systemu Linux: 5.15

Obsługa zaświadczania klucza modułu TPM

Wiele aplikacji polega na podstawowym zarządzaniu poświadczeniami kluczy i certyfikatów w celu ochrony przed kradzieżą poświadczeń, a jednym z głównych sposobów zapewnienia bezpieczeństwa poświadczeń jest zależność od dostawców magazynu kluczy, którzy zapewniają dodatkowe zabezpieczenia przed złośliwym oprogramowaniem i atakami. System Windows implementuje różnych dostawców kryptograficznych, którzy mogą być oprogramowaniem lub sprzętem.

Te dwa najważniejsze są:

  • Dostawca magazynu kluczy oprogramowania firmy Microsoft: standardowy dostawca, który przechowuje klucze oparte na oprogramowaniu i obsługuje CNG (Crypto-Next Generation)

  • Dostawca kryptograficzny platformy Microsoft: sprzęt, który przechowuje klucze w module TPM (moduł zaufanej platformy) i obsługuje również CNG

Za każdym razem, gdy dostawca magazynu jest używany, zwykle należy utworzyć parę kluczy pub/priv, która jest połączona z katalogiem głównym zaufania. Podczas tworzenia więcej właściwości można również użyć do włączenia niektórych aspektów magazynu kluczy, możliwości eksportowania itp. Kluczowe zaświadczanie w tym kontekście jest zdolnością techniczną do udowodnienia osobie odpowiadającej, że klucz prywatny został wygenerowany wewnątrz i jest zarządzany wewnątrz, i w niemożliwym do wyeksportowania formularzu. Takie zaświadczania klubowe z innymi informacjami mogą pomóc chronić przed kradzieżą poświadczeń i rodzajem odtwarzania ataku.

Moduły TPM zapewniają również możliwość zaświadczania, że klucze znajdują się w module TPM, co umożliwia zapewnienie wyższego poziomu zabezpieczeń, tworzenie kopii zapasowej przez nieeksportowalność, blokowanie młotków i izolowanie kluczy. Typowy przypadek użycia dotyczy aplikacji, które wystawiają certyfikat podpisu cyfrowego dla kluczy subskrybentów, sprawdzając, czy klucz podpisu prywatnego subskrybentów jest generowany i zarządzany w zatwierdzonym module TPM. Można łatwo potwierdzić fakt, że klucze znajdują się w prawidłowym module TPM z odpowiednimi flagami Brakportability przy użyciu zasad, jak pokazano poniżej.

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

Następne kroki