Considerazioni sulla sicurezza in relazione alla reflection

La reflection consente di ottenere informazioni su tipi e membri e di accedere ai membri, vale a dire chiamare metodi e costruttori, ottenere e impostare valori di proprietà, aggiungere e rimuovere gestori eventi e così via. L'uso della reflection per ottenere informazioni su tipi e membri non presenta limitazioni. L'intero codice può usare la reflection per eseguire le attività seguenti:

  • Enumerare tipi e membri ed esaminare i rispettivi metadati.

  • Enumerare ed esaminare assembly e moduli.

L'uso della reflection per accedere ai membri, per contro, è soggetto a limitazioni. A partire da .NET Framework 4, è possibile usare la reflection per accedere ai membri critici per la sicurezza solo tramite il codice attendibile. Inoltre, solo un codice affidabile può usare la reflection per accedere a membri non pubblici che non sarebbero altrimenti accessibili direttamente dal codice compilato. Infine, al codice in cui viene usata la reflection per accedere a un membro critico per la sicurezza devono essere associate le autorizzazioni richieste dal membro critico per la sicurezza, come nel codice compilato.

Fatte salve le autorizzazioni necessarie, il codice può usare la reflection per eseguire i tipi di accesso seguenti:

  • Accesso a membri pubblici non critici per la sicurezza.

  • Accesso a membri non pubblici ai quali il codice compilato potrebbe accedere, se non critici per la sicurezza. Gli esempi di tali membri non pubblici includono:

    • Membri protetti delle classi base del codice chiamante. Nella reflection viene fatto riferimento a questa operazione con il termine accesso a livello di famiglia.

    • Membri internal (membri Friend in Visual Basic) nell'assembly del codice chiamante. Nella reflection viene fatto riferimento a questa operazione con il termine accesso a livello di assembly.

    • Membri privati di altre istanze della classe che contiene il codice chiamante.

Ad esempio, il codice eseguito in un dominio applicazione in modalità sandbox è limitato all'accesso descritto in questo elenco, a meno che il dominio dell'applicazione non conceda altre autorizzazioni.

A partire da .NET Framework 2.0 Service Pack 1, il tentativo di accedere a membri generalmente non accessibili genera una richiesta del set di concessioni dell'oggetto di destinazione più ReflectionPermission con il flag ReflectionPermissionFlag.MemberAccess. Il codice eseguito con attendibilità totale (ad esempio il codice in un'applicazione avviata dalla riga di comando) è sempre in grado di soddisfare queste autorizzazioni. Tale codice è soggetto a limitazioni per quanto concerne l'accesso a membri critici per la sicurezza, come descritto più avanti in questo articolo.

Facoltativamente, un dominio di applicazioni sandbox può concedere ReflectionPermission con il flag ReflectionPermissionFlag.MemberAccess, come descritto nella sezione Accesso a membri generalmente non accessibili più avanti in questo articolo.

Accesso ai membri critici per la sicurezza

Un membro è critico per la sicurezza se possiede l'attributo SecurityCriticalAttribute, se appartiene a un tipo che possiede l'attributo SecurityCriticalAttribute o se è contenuto in un assembly critico per la sicurezza. A partire da .NET Framework 4, per l'accesso ai membri critici per la sicurezza valgono le regole seguenti:

  • Il codice Transparent non può usare la reflection per accedere a membri critici per la sicurezza, sebbene sia completamente attendibile. Viene generata un'eccezione MethodAccessException, FieldAccessException o TypeAccessException.

  • Il codice eseguito con attendibilità parziale è considerato Transparent.

Queste regole valgono sempre, indipendentemente dal fatto che l'accesso al membro critico per la sicurezza venga eseguito direttamente dal codice compilato o tramite reflection.

Il codice dell'applicazione eseguito dalla riga di comando viene eseguito con attendibilità totale. A condizione che non sia contrassegnato come Transparent, può usare la reflection per accedere a membri critici per la sicurezza. Quando lo stesso codice viene eseguito con attendibilità parziale, ad esempio in un dominio applicazione in modalità sandbox, il livello di attendibilità dell'assembly determina se può accedere o meno a codice critico per la sicurezza: se l'assembly è dotato di un nome sicuro ed è installato nella Global Assembly Cache, si tratta di un assembly attendibile e può chiamare membri critici per la sicurezza. Nel caso non sia attendibile, diventa Transparent anche se non è stato contrassegnato come tale e non può accedere a membri critici per la sicurezza.

Reflection e trasparenza

A partire da .NET Framework 4, Common Language Runtime determina il livello di trasparenza di un tipo o di un membro sulla base di diversi fattori, tra cui i livelli di attendibilità dell'assembly e del dominio dell'applicazione. La reflection fornisce le proprietà IsSecurityCritical, IsSecuritySafeCritical e IsSecurityTransparent, che consentono di individuare il livello di trasparenza di un tipo. La tabella seguente illustra le combinazioni valide di queste proprietà.

Livello di sicurezza IsSecurityCritical IsSecuritySafeCritical IsSecurityTransparent
Critico true false false
Critico per la sicurezza true true false
Modalità trasparente false false true

Usare queste proprietà è molto più semplice che non esaminare le annotazioni di sicurezza di un assembly e dei suoi tipi, controllare il livello di attendibilità corrente e tentare di duplicare le regole del runtime. Lo stesso tipo, ad esempio, può essere critico per la sicurezza quando viene eseguito dalla riga di comando, oppure trasparente per la sicurezza quando viene eseguito in un dominio applicazione in modalità sandbox.

Proprietà simili sono presenti nelle classi MethodBase, FieldInfo, TypeBuilder, MethodBuilder e DynamicMethod. Per le altre astrazioni di reflection e reflection emit, gli attributi di sicurezza vengono applicati ai metodi associati; nel caso delle proprietà, ad esempio, vengono applicati alle relative funzioni di accesso.

Accesso a membri generalmente non accessibili

Per usare la reflection per richiamare membri non accessibili secondo le regole di accessibilità di Common Language Runtime, è necessario concedere al codice una delle due autorizzazioni seguenti:

  • Per consentire al codice di richiamare qualsiasi membro non pubblico, è necessario concedere al codice l'autorizzazione ReflectionPermission con il flag ReflectionPermissionFlag.MemberAccess.

    Nota

    Per impostazione predefinita, i criteri di sicurezza negano questa autorizzazione al codice proveniente da Internet. L'autorizzazione, infatti, non dovrebbe mai essere concessa a codice proveniente da Internet.

  • Per consentire al codice di richiamare qualsiasi membro non pubblico, a condizione che il set di concessioni dell'assembly contenente il membro richiamato sia uguale o sia un sottoinsieme del set di concessioni dell'assembly contenente il codice chiamante: è necessario concedere al codice l'autorizzazione ReflectionPermission con il flag ReflectionPermissionFlag.RestrictedMemberAccess.

Ad esempio, si supponga di concedere a un dominio applicazione autorizzazioni Internet più ReflectionPermission con il flag ReflectionPermissionFlag.RestrictedMemberAccess, quindi di eseguire un'applicazione Internet con due assembly, A e B.

  • L''assembly A può usare la reflection per accedere ai membri privati dell'assembly B, in quanto il set di concessioni dell'assembly B non include autorizzazioni che non siano state concesse anche ad A.

  • L'assembly A non può usare la reflection per accedere ai membri privati degli assembly di .NET Framework, ad esempio mscorlib.dll, poiché mscorlib.dll è completamente attendibile e pertanto ha autorizzazioni che non sono state concesse all'assembly A. Viene generata una MemberAccessException quando la sicurezza dall'accesso di codice esamina lo stack in fase di esecuzione.

Serializzazione

Per la serializzazione, SecurityPermission con il flag SecurityPermissionAttribute.SerializationFormatter consente di ottenere e impostare membri di tipi serializzabili, indipendentemente dall'accessibilità. Questa autorizzazione consente di individuare e modificare lo stato privato di un'istanza tramite codice. Oltre a disporre delle autorizzazioni appropriate, il tipo deve essere contrassegnato come serializzabile nei metadati.

Parametri di tipo MethodInfo

È consigliabile evitare di scrivere membri pubblici che accettano parametri MethodInfo, specialmente per codice attendibile. Tali membri potrebbero risultare più vulnerabili al codice dannoso. Si consideri ad esempio un membro pubblico in codice a elevata attendibilità che accetta un parametro MethodInfo. Si supponga che il membro pubblico chiami indirettamente il metodo Invoke sul parametro specificato. Se il membro pubblico non esegue i controlli di autorizzazione necessari, la chiamata al metodo Invoke riuscirà sempre, poiché il sistema di sicurezza determina l'elevata attendibilità del chiamante. Anche se il codice dannoso non dispone dell'autorizzazione per richiamare direttamente il metodo, potrà chiamarlo indirettamente tramite una chiamata al membro pubblico.

Informazioni sulla versione

  • A partire da .NET Framework 4, il codice Transparent non può usare la reflection per accedere ai membri critici per la sicurezza.

  • Il flag ReflectionPermissionFlag.RestrictedMemberAccess è stato introdotto in .NET Framework 2.0 Service Pack 1. Le versioni precedenti di .NET Framework richiedono il flag ReflectionPermissionFlag.MemberAccess per il codice che usa la reflection per accedere ai membri non pubblici. Questa autorizzazione non dovrebbe mai essere concessa al codice parzialmente attendibile.

  • A partire da .NET Framework 2.0, l'uso della reflection per ottenere informazioni sui tipi non pubblici e i membri non richiedono autorizzazioni. Nelle versioni precedenti è necessario usare ReflectionPermission con il flag ReflectionPermissionFlag.TypeInformation.

Vedi anche