Ciągi przeznaczenia w ASP.NET Core

Składniki, które używają IDataProtectionProvider , muszą przekazać unikatowy parametr celów do CreateProtector metody . Parametr purposes jest nieodłączną częścią zabezpieczeń systemu ochrony danych, ponieważ zapewnia izolację między użytkownikami kryptograficznymi, nawet jeśli główne klucze kryptograficzne są takie same.

Gdy użytkownik określa cel, ciąg przeznaczenia jest używany wraz z głównymi kluczami kryptograficznymi w celu uzyskania podklucze kryptograficzne unikatowe dla tego konsumenta. To izoluje użytkownika od wszystkich innych odbiorców kryptograficznych w aplikacji: żaden inny składnik nie może odczytać ładunków i nie może odczytać żadnych ładunków innych składników. Ta izolacja renderuje również niewykonalne całe kategorie ataków na składnik.

Purpose Diagram Example

Na powyższym IDataProtector diagramie wystąpienia A i B nie mogą odczytywać ładunków siebie, tylko ich własnych.

Ciąg przeznaczenia nie musi być tajny. Powinien być po prostu unikatowy w tym sensie, że żaden inny dobrze zachowywany składnik nigdy nie będzie dostarczać tego samego ciągu przeznaczenia.

Napiwek

Używanie przestrzeni nazw i nazwy typu składnika korzystającego z interfejsów API ochrony danych jest dobrą regułą, ponieważ w praktyce te informacje nigdy nie będą powodować konfliktów.

Składnik utworzony przez firmę Contoso, który jest odpowiedzialny za wybicie tokenów elementu nośnego, może używać nazwy Contoso.Security.BearerToken jako ciągu przeznaczenia. Lub — jeszcze lepiej — może użyć nazwy Contoso.Security.BearerToken.v1 jako ciągu przeznaczenia. Dołączanie numeru wersji umożliwia przyszłej wersji używanie nazwy Contoso.Security.BearerToken.v2, a różne wersje będą całkowicie odizolowane od siebie, jeśli chodzi o ładunki.

Ponieważ parametr purposes to CreateProtector tablica ciągów, powyższe zamiast tego można określić jako [ "Contoso.Security.BearerToken", "v1" ]. Umożliwia to ustanowienie hierarchii celów i otwarcie możliwości obsługi wielu dzierżaw w systemie ochrony danych.

Ostrzeżenie

Składniki nie powinny zezwalać na wprowadzanie niezaufanych danych wejściowych użytkownika jako jedyne źródło danych wejściowych dla łańcucha celów.

Rozważmy na przykład składnik Contoso.Messaging.SecureMessage, który jest odpowiedzialny za przechowywanie bezpiecznych komunikatów. Jeśli składnik bezpiecznego przesyłania komunikatów miał wywołać CreateProtector([ username ])metodę , złośliwy użytkownik może utworzyć konto z nazwą użytkownika "Contoso.Security.BearerToken" w celu wywołania składnika CreateProtector([ "Contoso.Security.BearerToken" ]), co powoduje niezamierzone spowodowanie niezamierzonego wywołania bezpiecznego systemu obsługi komunikatów w celu wypęcenia ładunków, które mogą być postrzegane jako tokeny uwierzytelniania.

Lepszym łańcuchem celów dla składnika obsługi komunikatów jest CreateProtector([ "Contoso.Messaging.SecureMessage", $"User: {username}" ]), który zapewnia właściwą izolację.

Izolacja zapewniana przez i zachowania IDataProtectionProviderelementów , IDataProtectori jest następująca:

  • Dla danego IDataProtectionProvider obiektu metoda utworzy IDataProtector obiekt jednoznacznie powiązany zarówno z obiektemIDataProtectionProvider, który go utworzył, jak i parametrem purposes, który został CreateProtector przekazany do metody.

  • Parametr purpose nie może mieć wartości null. (Jeśli cele są określone jako tablica, oznacza to, że tablica nie może mieć zerowej długości, a wszystkie elementy tablicy muszą mieć wartość inną niż null). Pusty cel ciągu jest technicznie dozwolony, ale jest odradzany.

  • Dwa argumenty celów są równoważne, jeśli i tylko wtedy, gdy zawierają te same ciągi (przy użyciu porównania porządkowego) w tej samej kolejności. Pojedynczy argument przeznaczenia jest odpowiednikiem tablicy celów pojedynczego elementu.

  • Dwa IDataProtector obiekty są równoważne, jeśli i tylko wtedy, gdy są tworzone na podstawie równoważnych IDataProtectionProvider obiektów z równoważnymi parametrami celów.

  • W przypadku danego IDataProtector obiektu wywołanie Unprotect(protectedData) metody zwróci oryginał unprotectedData , jeśli i tylko wtedy, gdy protectedData := Protect(unprotectedData) dla równoważnego IDataProtector obiektu.

Uwaga

Nie rozważamy przypadku, w którym jakiś składnik celowo wybiera ciąg przeznaczenia, który jest znany jako konflikt z innym składnikiem. Taki składnik zasadniczo byłby uważany za złośliwy, a ten system nie ma na celu zapewnienia gwarancji bezpieczeństwa w przypadku, gdy złośliwy kod jest już uruchomiony wewnątrz procesu roboczego.