安全透明代码不应引用非公共的安全关键成员
更新:2007 年 11 月
TypeName |
SecurityTransparentCodeShouldNotReferenceNonpublicSecurityCriticalCode |
CheckId |
CA2129 |
类别 |
Microsoft.Security |
是否重大更改 |
是 |
原因
标有 SecurityTransparentAttribute 的方法调用标记为 SecurityCritical 的非公共成员。SecurityTransparent 是方法的默认标记。
规则说明
.NET Framework 2.0 引入了一个称为“透明度”的功能。各个方法、字段、接口、类和类型都可以是透明或关键的。
不允许透明代码提升安全特权。因此,授予透明代码或其请求的任何权限都会自动通过该代码传递给调用方或主机 AppDomain。提升的示例包括 Assert、LinkDemand、SuppressUnmanagedCode 和 unsafe 代码。
将透明代码和关键代码分离的目的是为了简化安全审核流程。通常在公共入口点执行审核,这是因为公共入口点可能会被恶意和不受信任地公开使用。通过将程序集的较小节标记为关键,安全审核的范围可以缩小到公共入口点以及提升特权的代码的安全关键区。但是,为了确保审核的准确和完整,必须尽量严格地在透明代码和关键代码之间强制相应的界限。另一种方法是允许透明代码调用内部安全关键代码,这要求对透明代码进行更严格的审核。
在运行时,公共语言运行时实时编译器检查透明代码是否正在引用或调用非公共安全关键代码。如果透明代码调用非公共关键代码,将引发异常,例如 MethodAccessException。此种情况的处理方法类似于一个类试图访问另一个类的私有成员的情况。
此代码分析规则分析透明/关键混合程序集中的所有方法和类型。此规则还标记从透明代码到未标记为 SecurityTreatAsSafe 的非公共关键代码的任何调用。
如何修复冲突
若要解决该问题,请将调用非公共 SecurityCritical 代码的代码标记为 SecurityCritical,或者将目标方法/类型标记为 SecurityTreatAsSafe。这样可以有效地将代码视为公共安全的,并且通过审核避免将其用于恶意目的。
何时禁止显示警告
不要禁止显示此规则发出的消息。
示例
由于 SecondSecurityMethod 是私有的并且是 SecurityCritical,下面的代码将失败。作为安全问题的一个示例,SecondSecurityMethod 中的 Assert 将阻止特权操作和调出中的所有请求流向 FirstSecurityMethod,从而避免只对调用方执行安全检查。
using System;
using System.Security.Permissions;
namespace SecurityTestClassLibrary
{
public class SecurityTestClass
{
// SecurityTransparent
public void FirstSecurityMethod()
{
SecondSecurityMethod();
}
[System.Security.SecurityCritical]
private void SecondSecurityMethod()
{
// Assert permissions
// do privileged actions, such as method call-outs
}
}
}
如果未强制透明/关键界限,FirstSecurityMethod 将可以执行 SecondSecurityMethod 的所有操作,而无需进行安全检查。
一种方法是对该方法进行代码评审,如果该方法被认为可以安全提升并且不会受到恶意攻击,可以将其标记为 SecurityTreatAsSafe:
using System;
using System.Security.Permissions;
namespace SecurityTestClassLibrary
{
public class SecurityTestClass
{
// SecurityTransparent
public void FirstSecurityMethod()
{
SecondSecurityMethod();
}
[System.Security.SecurityTreatAsSafe]
[System.Security.SecurityCritical]
private void SecondSecurityMethod()
{
// Assert permissions
// do privileged actions, such as method call-outs
}
}
}
另一种方法是将 Method1 也标记为 Critical。这样可以扩展程序集的关键内核,并增加安全审核的大小。还确保执行相应的威胁建模和代码流分析。
using System;
using System.Security.Permissions;
namespace SecurityTestClassLibrary
{
public class SecurityTestClass
{
[System.Security.SecurityCritical]
public void FirstSecurityMethod()
{
SecondSecurityMethod();
}
[System.Security.SecurityCritical]
private void SecondSecurityMethod()
{
// Assert permissions
// do privileged actions, such as method call-outs
}
}
}