SYSK 259: Is ‘internal’ class modifier a sufficient level of protection?


So, say you have a class that you’d like to make sure that nobody outside of your company (or your product/project team) can use.  As an example, I’ll use an encryption class (see below) with Encrypt and Decrypt methods:


 


internal class Encryption


{


    internal string Encrypt(string input)


    {


        return “Encrypted…”;


    }


 


    internal string Decrypt(string input)


    {


        return “Decrypted…”;


    }


}


 


You might think that using internal class and method modifiers are sufficient security…  After all, ildasm would show the class as private, and attempting to instantiate this class from another assembly would result in a compile time error ‘ClassLibrary1.Encryption’ is inaccessible due to its protection level.


 


However, with same ildasm tool, you can get the signature of internal, private and protected methods…  not just public.  With that, if you’re willing to write a bit of code using reflection, you can easily bypass the compile time error.  E.g. the code below returns the expected value of “Encrypted…”:


 


object x = Activator.CreateInstanceFrom(“ClassLibrary1.dll”, “ClassLibrary1.Encryption”).Unwrap();


 


string result = x.GetType().InvokeMember(“Encrypt”,


        System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic,


        null, x, new object[] { “string to be encrypted” }) as string;


 


And now, if a hacker got a hold of your server, he/she doesn’t have to decrypt your sensitive data…  they only need to invoke your code that’ll do it for them…


 


Same is true not only for your internal classes, but also internal and even private classes within the .NET framework (see the bottom of this post for a sample). 


 



So, what’s my point?  Using class and method modifiers like internal or private is insufficient for protecting it from being invoked by unauthorized applications/users.  In my projects I always add evidence based security for sensitive classes/methods, e.g.:


[StrongNameIdentityPermissionAttribute(SecurityAction.LinkDemand, PublicKey = YourCompany.YourProject.PublicKey)]


public string Encrypt(string message)


 


 


Appendix


 


Below is a snippet of code that instantiates and uses an internal .NET class (note: undocumented classes are not guaranteed to be preserved or work same way in future version.  Do not use them!):


System.Reflection.Assembly assmbly = typeof(System.IO.Compression.GZipStream).Assembly;


Type t = assmbly.GetType(“System.IO.Compression.FastEncoder”);


 


System.Reflection.ConstructorInfo ci = t.GetConstructor(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public,


    null, new Type[] { typeof(bool) }, new System.Reflection.ParameterModifier[] { });


 


object fastEnc = null;


if (ci != null)


    fastEnc = ci.Invoke(new object[] { false });    // false = !GZip


else


    System.Diagnostics.Debug.Assert(false, string.Format(“Unable to instanciate {0} class”, t.Name));


 


byte[] input = System.Text.Encoding.Unicode.GetBytes(“Source data”);


int startIndex = 0;


int count = input.Length;


 


t.InvokeMember(“SetInput”,


    System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public,


    null, fastEnc, new object[] { input, startIndex, count });


 


byte[] outputBuffer = new byte[2048];


int charactersWritten = (int)t.InvokeMember(“GetCompressedOutput”,


    System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public,


    null, fastEnc, new object[] { outputBuffer });


 


 


System.Reflection.Assembly assmbly = System.Reflection.Assembly.LoadFrom(“WindowsApplication1.exe”);


 


Type encType = assmbly.GetType(“WindowsApplication1.Encryption”);


System.Reflection.ConstructorInfo ci = encType.GetConstructor(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public,


    null, new Type[] { }, new System.Reflection.ParameterModifier[] { });


object enc = ci.Invoke(new object[] { });


 


string encString = (string) encType.InvokeMember(“Encrypt”,


    System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic,


    null, enc, new object[] { “string to be encrypted” });


 


string decString = (string) encType.InvokeMember(“Decrypt”,


    System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic,


    null, enc, new object[] { encString });


 


 


 

Comments (3)

  1. Daniel says:

    Note that this only works in a partially trusted environment (see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/PAGGuidelines0003.asp):

    "In .NET 2.0, any fully trusted assembly will satisfy any demand, including a link demand for an identity permission such as a System.Security.Permissions.StrongNameIdentityPermission that the assembly does not satisfy."

  2. c.j. anderson (stand__sure) says:

    great piece.  thank you for the tip!  

  3. Alex J. Lee says:

    I have a question about using System.Reflection.BindingFlags.InvokeMethod.

    Actually, I am using InvokeMethod of Reflection in WebService to call a private method on .NET Framework 1.1.

    But, I have read some articles that using Invoke method of Reflection can be slower than calling a method directly about 1 thousnad times.

    If it is true, it is really critical thing to us.

    So, I tried to find out any documents from Microsoft Web Site but fail.

    So…

    Could you give me the correct information about this?

    Regads,

    Alex J. Lee

    Product Developer