Stringhe di scopo in ASP.NET Core

I componenti che utilizzano IDataProtectionProvider devono passare un parametro univoco per scopi al CreateProtector metodo . Il parametro di scopo è intrinseco alla sicurezza del sistema di protezione dei dati, in quanto fornisce l'isolamento tra i consumer di crittografia, anche se le chiavi crittografiche radice sono le stesse.

Quando un consumer specifica uno scopo, la stringa di scopo viene usata insieme alle chiavi di crittografia radice per derivare sottochiavi crittografiche univoche per tale consumer. In questo modo il consumer viene isolato da tutti gli altri consumer crittografici nell'applicazione: nessun altro componente può leggere i payload e non può leggere i payload di altri componenti. Questo isolamento esegue anche il rendering infeasible di intere categorie di attacchi contro il componente.

Purpose Diagram Example

Nel diagramma precedente, IDataProtector le istanze A e B non possono leggere i payload dell'altro, solo i propri.

La stringa di scopo non deve essere segreta. Dovrebbe essere semplicemente univoco nel senso che nessun altro componente ben comportato fornirà mai la stessa stringa di scopo.

Suggerimento

L'uso dello spazio dei nomi e del nome del tipo del componente che utilizza le API di protezione dei dati è una buona regola generale, perché in pratica queste informazioni non saranno mai in conflitto.

Un componente creato da Contoso responsabile della creazione di token di connessione potrebbe usare Contoso.Security.BearerToken come stringa di scopo. Oppure, ancora meglio, potrebbe usare Contoso.Security.BearerToken.v1 come stringa di scopo. L'aggiunta del numero di versione consente a una versione futura di usare Contoso.Security.BearerToken.v2 come scopo e le diverse versioni saranno completamente isolate l'una dall'altra per quanto riguarda i payload.

Poiché il parametro a scopo di CreateProtector è una matrice di stringhe, è possibile che il parametro precedente sia stato specificato come [ "Contoso.Security.BearerToken", "v1" ]. Ciò consente di stabilire una gerarchia di scopi e apre la possibilità di scenari multi-tenancy con il sistema di protezione dei dati.

Avviso

I componenti non devono consentire l'input utente non attendibile come unica origine di input per la catena di scopi.

Si consideri ad esempio un componente Contoso.Messaging.SecureMessage responsabile dell'archiviazione di messaggi sicuri. Se il componente di messaggistica sicura doveva chiamare , un utente malintenzionato potrebbe creare un account con nome utente "Contoso.Security.BearerToken" nel tentativo di chiamare CreateProtector([ username ])CreateProtector([ "Contoso.Security.BearerToken" ])il componente, causando inavvertitamente il sistema di messaggistica sicura a payload che potrebbero essere percepiti come token di autenticazione.

Una catena di scopi migliore per il componente di messaggistica è CreateProtector([ "Contoso.Messaging.SecureMessage", $"User: {username}" ]), che fornisce un isolamento appropriato.

L'isolamento fornito da e i comportamenti di IDataProtectionProvider, IDataProtectore sono i seguenti:

  • Per un determinato IDataProtectionProvider oggetto, il CreateProtector metodo creerà un IDataProtector oggetto associato in modo univoco all'oggetto IDataProtectionProvider che lo ha creato e al parametro di scopo passato al metodo .

  • Il parametro purpose non deve essere Null. Se gli scopi vengono specificati come matrice, significa che la matrice non deve essere di lunghezza zero e tutti gli elementi della matrice devono essere non null. Uno scopo stringa vuoto è tecnicamente consentito, ma è sconsigliato.

  • Due argomenti di scopo sono equivalenti se e solo se contengono le stesse stringhe (usando un operatore di confronto ordinale) nello stesso ordine. Un argomento a scopo singolo equivale alla matrice a scopo singolo elemento corrispondente.

  • Due IDataProtector oggetti sono equivalenti se e solo se vengono creati da oggetti equivalenti con parametri di scopo equivalenti IDataProtectionProvider .

  • Per un determinato IDataProtector oggetto, una chiamata a Unprotect(protectedData) restituirà l'originale unprotectedData se e solo se protectedData := Protect(unprotectedData) per un oggetto equivalente IDataProtector .

Nota

Non viene considerato il caso in cui alcuni componenti scelgono intenzionalmente una stringa di scopo che è nota per essere in conflitto con un altro componente. Tale componente sarebbe essenzialmente considerato dannoso e questo sistema non è progettato per fornire garanzie di sicurezza nel caso in cui il codice dannoso sia già in esecuzione all'interno del processo di lavoro.