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:
type
is only used as shown above. No attempt is made to instantiate the type.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.
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.
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.
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.
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));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With