Is it safe to call Type.GetType with an untrusted type name?

.net, asp.net, c#, security

Solution

No, this is not safe at all. Type.GetType will load an assembly if it has not been loaded before:

GetType causes loading of the assembly specified in typeName.

So what's wrong with loading an assembly? Aside from it using additional memory as Daniel points out, .NET assemblies can execute code when they load, even though this functionality is not exposed to normal compilers like C# and VB.NET. These are called module initializers.

The module’s initializer method is executed at, or sometime before, first access to any types, methods, or data defined in the module

Just the fact that you are loading an assembly and examining its types is enough to get the module initializer to run.

Someone with a cleverly written assembly (say by using ilasm and writing raw MSIL) can execute code just by getting the assembly loaded and you examining the types. That's why we have Assembly.ReflectionOnlyLoad, so we can safely load the assembly in a non-executable environment.

I did a little more thinking about this and thought of a few more cases.

Consider that your Application Pool is set to run 64-bit. Now imagine that your attacker uses the AJAX service to attempt to load an assembly that is strictly for x86 architecture only. For example, there is one in my GAC called Microsoft.SqlServer.Replication that is x86 only, there is no AMD64 counter-part. If I ask your service to load that assembly, you'd get a `BadImageFormatException`. Depending on what guard clauses you have in place around loading the assembly, unhandled exceptions could completely bring down your AppPool.

Problem

I came across the following in a code review: ``` Type type = Type.GetType(typeName); if (type == typeof(SomeKnownType)) DoSomething(...); // does not use type or typeName ``` `typeName` originates from an AJAX request and is not validated. Does this pose any potential security issues? For example, is it possible for unexpected code to be executed, or for the entire application to crash (denial of service), as the result of loading arbitrary types from arbitrary assemblies? (I suppose some joker could attempt to exhaust available memory by loading every type from every assembly in the GAC. Anything worse?) Notes: - This is an ASP.NET application running under Full Trust. - The resulting `type` is only used as shown above. No attempt is made to instantiate the type.

Original source