反射的安全注意事项
更新:2007 年 11 月
反射提供获取有关类型和成员信息以及访问成员的功能。访问非公共成员可能会带来安全危险。因此,访问非公共成员的代码需要带有适当标志的 ReflectionPermission。此外,某些任务(例如提供证据、执行非托管代码以及序列化对象)还需要 SecurityPermission。
在未经许可的情况下,所有代码都可以使用反射来执行以下任务:
枚举类型和成员并验证其元数据。
枚举并验证程序集和模块。
访问公共成员。
访问调用代码的基类的 protected 成员。(在反射中,将此称为系列级访问。)
访问调用代码的程序集中的 internal 成员(在 Visual Basic 中为 Friend 成员)。(在反射中,将此称为程序集级访问。)
访问非公共成员
若要使用反射来调用根据公共语言运行库的可访问性规则不可访问的成员,必须向您的代码授予以下两种权限之一:
允许代码调用任何非公共成员:带有 ReflectionPermissionFlag.MemberAccess 标志的 ReflectionPermission。
说明: 默认情况下,安全策略拒绝向源自 Internet 的代码授予此权限。决不应向源自 Internet 的代码授予此权限。
允许代码调用任何非公共成员(前提是包含被调用成员的程序集的授权集与包含调用该代码的程序集的授权集相同,或与包含调用该代码的程序集的授权集的子集相同):带有 ReflectionPermissionFlag.RestrictedMemberAccess 标记的 ReflectionPermission。
例如,假定向某个应用程序域授予 Internet 权限以及带有 ReflectionPermissionFlag.RestrictedMemberAccess 标记的 ReflectionPermission,然后运行具有 A 和 B 两个程序集的 Internet 应用程序。
因为程序集 B 的授权集不包含任何未授予 A 的权限,因此程序集 A 可以使用反射访问程序集 B 的私有成员。
程序集 A 不能使用反射访问 .NET Framework 程序集(如 mscorlib.dll)的私有成员,其原因是:由于 mscorlib.dll 是完全受信任的,因此 mscorlib.dll 具有未授予程序集 A 的权限。当代码访问安全在运行时审核堆栈时,会引发一个 MemberAccessException。
有关授予具有 ReflectionPermissionFlag.RestrictedMemberAccess 标志的 ReflectionPermission 的沙盒应用程序域的示例,请参见演练:从部分信任的方案中发出代码。
序列化
对于序列化,带有 SecurityPermissionAttribute.SerializationFormatter 标志的 SecurityPermission 提供获取并设置可序列化类型的成员的功能,无论这些可序列化类型的成员是否可以访问。此权限可以使代码发现并更改实例的私有状态。(除了授予正确的权限之外,还必须在元数据中将类型标记为可序列化。)
链接请求检查
如果一个方法或委托具有对权限 P 的 LinkDemand,运行库将对该方法或委托的调用方执行链接请求检查,以验证是否已向调用方授予权限 P。对于类型信息发现和调用,都会进行此链接请求检查。
避免创作 MethodInfo 类型的参数
应避免编写采用 MethodInfo 参数的公共 API,对于高度受信任的代码尤其如此。这样的 API 可能更容易受到恶意代码的攻击。例如,设想在高度受信任的代码中有一个采用 MethodInfo 参数的公共 API。假设此公共 API 对所提供的参数间接地调用 Invoke 方法。如果公共 API 没有执行必要的权限检查,由于安全系统断定调用方受到高度信任,对 Invoke 方法的调用将始终会成功。即使恶意代码无权直接调用该方法,它仍然能够通过调用公共 API 来间接地调用该方法。
版本信息
ReflectionPermissionFlag.RestrictedMemberAccess 标志是在 .NET Framework 2.0 Service Pack 1 中引入的。对于使用反射访问非公共成员的代码,早期版本的 .NET Framework 需要 ReflectionPermissionFlag.MemberAccess 标志。决不应将此权限授予部分受信任的代码。
说明: |
---|
若要使用 ReflectionPermissionFlag.RestrictedMemberAccess 标志,您的应用程序应面向 .NET Framework 3.5 版。有关更多信息,请参见 .NET Framework 3.5 体系结构。 |
从 .NET Framework 2.0 开始,使用反射获取有关非公共类型和成员的信息不需要任何权限。在早期版本中,带有 ReflectionPermissionFlag.TypeInformation 标志的 ReflectionPermission 是必需的。