C# 使用不受信任的类型名调用Type.GetType安全吗?

C# 使用不受信任的类型名调用Type.GetType安全吗?,c#,asp.net,.net,security,C#,Asp.net,.net,Security,我在一次代码审查中遇到了以下问题: Type type = Type.GetType(typeName); if (type == typeof(SomeKnownType)) DoSomething(...); // does not use type or typeName typeName源自AJAX请求,未经验证这是否会带来任何潜在的安全问题?例如,是否可能执行意外的代码,或整个系统 从任意程序集中加载任意类型导致应用程序崩溃(拒绝服务) (我想一些小丑可能会试图通过加载GAC

我在一次代码审查中遇到了以下问题:

Type type = Type.GetType(typeName);
if (type == typeof(SomeKnownType))
    DoSomething(...); // does not use type or typeName
typeName
源自AJAX请求,未经验证这是否会带来任何潜在的安全问题?例如,是否可能执行意外的代码,或整个系统 从任意程序集中加载任意类型导致应用程序崩溃(拒绝服务)

(我想一些小丑可能会试图通过加载GAC中每个程序集中的每个类型来耗尽可用内存。还有更糟的吗?)

注:

  • 这是一个在完全信任下运行的ASP.NET应用程序
  • 产生的
    类型
    仅如上所示使用。未尝试实例化该类型

如果库不在内存中,它可能会占用内存

我会有一本
字典
作为允许的列表

var whitelist = new Dictionary<string, Type>;
whitelist.Add("MyType", typeof(MyType));
var白名单=新字典;
白名单。添加(“MyType”,typeof(MyType));

引用类型本身没有继承危险。对.NET的信任处于程序集级别。如果没有包含指定类型的可用程序集,则调用将只返回null。因此,必须有人为代码提供程序集——程序集不是凭空出现的。

不,这一点都不安全。如果以前未加载程序集,则将加载该程序集:

GetType导致加载typeName中指定的程序集

那么加载程序集有什么问题?除此之外,正如Daniel指出的那样,使用额外的内存,.NET程序集可以在加载时执行代码,即使这种功能不暴露于C#和VB.NET等普通编译器。这些被称为

模块的初始值设定项方法在首次访问模块中定义的任何类型、方法或数据时或之前执行

只要加载程序集并检查其类型,就足以让模块初始值设定项运行

拥有一个编写巧妙的程序集(比如使用ilasm和编写原始MSIL)的人可以通过加载程序集和检查类型来执行代码。这就是为什么我们有,所以我们可以在一个不可执行的环境中安全地加载程序集


我对此做了更多的思考,并思考了更多的案例



请考虑将应用程序池设置为运行64位。现在想象一下,攻击者使用AJAX服务试图加载仅适用于x86体系结构的程序集。例如,我的GAC中有一个名为Microsoft.SqlServer.Replication的仅限x86,没有AMD64计数器部件。如果我要求您的服务加载该程序集,您将得到一个
BadImageFormatException
。根据加载程序集时使用的保护子句,未处理的异常可能会完全消失。

这可能会增加内存使用量。对于一个非常有趣的问题,您不能给出从字符串到
类型的白名单映射吗?+1。我不知道GetType有什么副作用(比如实例化),但是一个规范的答案会非常有趣!旁注,我希望所有的问题都这么清楚,包括所有第一次相关的信息等。呼吸新鲜空气!没有关于安全性的评论,但这完全不需要,因为它应该相当于
typeName==typeof(SomeKnownType).AssemblyQualifiedName
。我看到的一个理论上的可能性是,有人能够以某种方式将程序集放到服务器上(通过一些其他漏洞或一些文件上载功能等),然后使用此代码加载该程序集。不确定是否可以执行任何操作,但请查看不允许执行的操作。@LB2我的回答中也有这个问题。使用字典仍然需要基于用户定义的字符串创建
类型
对象,所以所有这些问题都存在。@Daniel:你确定
Type.GetType
调用静态构造函数吗?@MichaelLiu我很确定。@MichaelLiu它没有。刚刚测试过。加载磁盘上已经存在的程序集有危险吗?(假设攻击者无法上载任意程序集,但现有程序集中可能存在安全漏洞。)@MichaelLiu我无法想象加载程序集会内在触发代码运行的原因。它只是将程序集加载到内存中。这不会执行任何东西。@Servy:我知道加载本机DLL将执行DllMain中的代码。托管程序集是否不同?Wr.<代码>类型。GETYTYPE 拒绝加载本地DLL?米迦勒,请考虑此。在ajax请求中公开您的实现(类型名称)可能是不明智的。也许传递枚举值并让代码对其求值以静态方式而不是动态方式查找类型会更明智。那么你的问题就不成问题了。@codenoire:真的。这是我正在审阅的其他人的代码。您不能用C#添加的代码,很好!把一种没人能发现的病毒植入体内的好方法:(@BradleyDotNET-这是一个令人困惑的说法。你可以通过反汇编或反编译找到代码,这就是你如何找到程序集中提供的任何其他代码的方法。这与旧的基于PE的病毒几乎没有什么不同,它们会嵌入PE格式。但是你的产品上会有这样一个恶意程序集吗Ever,如果是这样,不会有任何安全漏洞,使它的安全漏洞变得相当不可靠吗?“Service,我不会冒险。模块初始化器很可能存在于管理C++中的任何东西(这主要是CLR支持这个特性的原因),它们很容易在GAC中结束。(例如,支持.NET框架框架,用于托管C++)。假设它们可能做的是无害的事情,但可能足以破坏应用程序拒绝服务。