Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.
like image 636
Michael Liu Avatar asked May 27 '14 17:05

Michael Liu


People also ask

How does type GetType work?

GetType() call on each assembly in the list and passing in the type's full name. Type. GetType() will most likely be using the references of the currently assembly to resolve the type, so if the type exists in an assembly that is not a reference, it will not be found.

What is GetType C#?

GetType Method is used to find the type of the current instance. This method returns the instances of the Type class that are used for consideration.

How do you get type objects from assemblies that are not already loaded?

GetTypes to obtain Type objects from assemblies that have not been loaded, passing in the name of the type or types you want. Use Type. GetType to get the Type objects from an assembly that is already loaded.


2 Answers

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.

like image 121
vcsjones Avatar answered Sep 28 '22 06:09

vcsjones


It could eat up memory potentially if the libraries aren't in memory.

I would have a Dictionary<string, Type> as an allowed list.

var whitelist = new Dictionary<string, Type>; whitelist.Add("MyType", typeof(MyType)); 
like image 38
Daniel A. White Avatar answered Sep 28 '22 05:09

Daniel A. White