Zweckzeichenfolgen in ASP.NET Core

Komponenten, die IDataProtectionProvider nutzen, müssen an die CreateProtector-Methode einen eindeutigen Zweck-Parameter übergeben. Der Zweck-Parameter ist ein wesentlicher Bestandteil der Sicherheit des Datenschutzsystems, da er eine Isolation zwischen kryptografischen Consumern ermöglicht, selbst wenn die kryptografischen Stammschlüssel identisch sind.

Wenn ein Consumer einen Zweck angibt, wird die Zweckzeichenfolge zusammen mit den kryptografischen Stammschlüsseln verwendet, um kryptografische Unterschlüssel abzuleiten, die nur für diesen Consumer eindeutig sind. Dadurch wird der Consumer von allen anderen kryptographischen Consumern in der Anwendung isoliert. Keine andere Komponente kann seine Nutzdaten lesen, und er kann die Nutzdaten keiner anderen Komponente lesen. Diese Isolation macht auch ganze Kategorien von Angriffen auf die Komponente undurchführbar.

Purpose Diagram Example

Im obigen Diagramm können die IDataProtector-Instanzen A und B nicht die Nutzdaten der jeweils anderen lesen, sondern nur ihre eigenen.

Die Zweckzeichenfolge muss nicht geheim sein. Sie muss in dem Sinne eindeutig sein, dass keine andere ordnungsgemäß funktionierende Komponente jemals dieselbe Zweckzeichenfolge bereitstellt.

Tipp

Die Verwendung von Namespace und Typname der Komponente, die die Datenschutz-APIs nutzt, ist eine gute Faustregel, da diese Informationen in der Praxis nie in Konflikt stehen werden.

Eine von Contoso entwickelte Komponente, die für das Ausstellen von Token zuständig ist, kann Contoso.Security.BearerToken als Zweckzeichenfolge verwenden. Oder sie kann – noch besser – Contoso.Security.BearerToken.v1 als Zweckzeichenfolge nutzen. Durch das Anfügen der Versionsnummer kann eine künftige Version Contoso.Security.BearerToken.v2 als Zweck verwenden, wodurch die verschiedenen Versionen in Bezug auf Nutzdaten vollständig voneinander isoliert bleiben.

Da der Zweckparameter für CreateProtector ein Zeichenfolgenarray ist, kann die obige Angabe stattdessen als [ "Contoso.Security.BearerToken", "v1" ] erfolgen. Dies ermöglicht eine Zweckhierarchie und eröffnet die Möglichkeit mehrinstanzenfähiger Szenarien mit dem Datenschutzsystem.

Warnung

Komponenten dürfen nicht zulassen, dass nicht vertrauenswürdige Benutzereingaben die einzige Eingabequelle für die Zweckkette sind.

Betrachten Sie beispielsweise die Komponente Contoso.Messaging.SecureMessage, die für das Speichern sicherer Nachrichten zuständig ist. Wenn die sichere Messagingkomponente CreateProtector([ username ]) aufruft, könnte ein böswilliger Benutzer ein Konto mit dem Benutzernamen Contoso.Security.BearerToken erstellen, um zu versuchen, die Komponente zum Aufrufen von CreateProtector([ "Contoso.Security.BearerToken" ]) zu veranlassen. Dadurch würde das sichere Messagingsystem versehentlich Nutzdaten ausstellen, die als Authentifizierungstoken wahrgenommen werden könnten.

Eine bessere Zweckkette für die Messagingkomponente wäre CreateProtector([ "Contoso.Messaging.SecureMessage", $"User: {username}" ]), wodurch eine ordnungsgemäße Isolation ermöglicht wird.

Die Isolation durch und das Verhalten von IDataProtectionProvider, IDataProtector und die Zwecke sind wie folgt:

  • Für ein bestimmtes IDataProtectionProvider-Objekt erstellt die CreateProtector-Methode ein IDataProtector-Objekt, das eindeutig sowohl an das IDataProtectionProvider-Objekt, das es erstellt hat, als auch an den Zweckparameter, der an die Methode übergeben wurde, gebunden ist.

  • Der Zweckparameter darf nicht NULL sein. (Wenn Zwecke als Array angegeben werden, bedeutet dies, dass das Array nicht die Länge 0 haben darf und dass alle Elemente des Arrays ungleich NULL sein müssen.) Die Angabe einer leeren Zweckzeichenfolge ist technisch zulässig, aber nicht empfehlenswert.

  • Zwei Zweckargumente sind nur dann gleichwertig, wenn sie die gleichen Zeichenfolgen (unter Verwendung eines Ordinalvergleichs) in der gleichen Reihenfolge enthalten. Ein einzelnes Zweckargument entspricht dem entsprechenden Array für Zwecke mit einem einzelnen Element.

  • Zwei IDataProtector-Objekte sind nur dann gleichwertig, wenn sie aus gleichwertigen IDataProtectionProvider-Objekten mit gleichwertigen Zweckparametern erstellt wurden.

  • Für ein gegebenes IDataProtector-Objekt gibt ein Aufruf von Unprotect(protectedData) nur dann das ursprüngliche unprotectedData zurück, wenn protectedData := Protect(unprotectedData) für ein gleichwertiges IDataProtector-Objekt gilt.

Hinweis

Wir betrachten nicht den Fall, bei dem eine Komponente absichtlich eine Zweckzeichenfolge wählt, von der bekannt ist, dass sie mit einer anderen Komponente in Konflikt steht. Eine solche Komponente wäre im Grunde genommen als schädlich anzusehen, und dieses System ist nicht dazu gedacht, Sicherheitsgarantien für den Fall zu bieten, dass schädlicher Code bereits innerhalb des Workerprozesses ausgeführt wird.