Uso di reflection per invocare metodi interni

In un post precedente ho parlato dell’uso dell’attributo AllowPartiallyTrustedCallers a proposito della sicurezza applicata all’invocazione di metodi pubblici definiti all’interno di un assembly strong-named.  Rimanendo sempre sullo stesso tema, un altro attributo utile a “limitare” i possibili chiamanti di un determinato metodo è StrongNameIdentityPermissionAttribute, usato in questo modo:

[StrongNameIdentityPermissionAttribute(SecurityAction.LinkDemand, PublicKey = “public key”)]
public string MyMethod(string parameter) {}

La presenza di questo attributo permette la chiamata al metodo MyMethod dell’esempio solo al codice contenuto in un assembly firmato con strong name e che presenta la chiave pubblica specificata nell’attributo stesso. Qualsiasi altro codice che tentasse di invocare il metodo in questione provoca una eccezione del tipo SecurityException. Questa forma di sicurezza è la più affidabile a disposizione se vogliamo proteggere ad esempio metodi sensibili dall’invocazione da parte di codice maligno. Se invece il metodo in questione non è invocato dall’esterno dell’assembly, in altre parole non è public, potremmo pensare che basterebbe limitare il suo ambito di visibilità (es.: private, internal in C# oppure friend in VB.NET) per renderlo sicuro da chiamate da parte di codice non affidabile. Putroppo questa convinzione è errata, poichè attraverso l’uso delle tecniche di reflection può essere invocato qualsiasi metodo con qualsiasi ambito di visibilità, quindi anche i metodi marcati come internal o private. Infatti, utilizzando il tool Reflector oppure semplicemente ildasm è possibile leggere la firma di metodi con qualsiasi visibilità (quindi public, private, protected ed internal). Se il metodo MyMethod fosse “internal”, conoscendo la sua firma è possibile invocarlo da un altro assembly via reflection in questo modo:

object x = Activator.CreateInstanceFrom(“MyAssembly.dll”, “MyAssembly.MyNamespace”).Unwrap();
string result = x.GetType().InvokeMember(“MyMethod”, System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance  
      | System.Reflection.BindingFlags.NonPublic, null, x, new object[] { “string parameter” }) as string;

bypassando quindi la protezione imposta dal livello di visibilità.

Da notare che richiamare un metodo non pubblico attraverso reflection richiede il permesso ReflectionPermission, impostabile attraverso l’uso dell’attributo ReflectionPermissionAttribute (in modo dichiarativo), oppure in modo programmatico.

In assenza di questo permesso è possibile invocare via reflection solo i metodi pubblici.