更新:2007 年 11 月
| TypeName | AptcaTypesShouldOnlyExtendAptcaBaseTypes | 
| CheckId | CA2117 | 
| 类别 | Microsoft.Security | 
| 是否重大更改 | 是 | 
原因
具有 System.Security.AllowPartiallyTrustedCallersAttribute 属性的程序集中的公共或受保护类型继承自没有该属性的程序集中声明的类型。
规则说明
默认情况下,具有强名称的程序集中的公共或受保护类型受到针对完全信任的 继承要求 的显式保护。用 AllowPartiallyTrustedCallersAttribute (APTCA) 属性标记的具有强名称的程序集没有此保护。此属性禁用继承要求。这样,将使在程序集中声明的公开类型可以由不具有完全信任的类型继承。
如果完全受信任的程序集具有 APTCA 属性,并且程序集中的类型所继承的类型不允许部分受信任的调用方,则可能会产生安全问题。如果两个类型 T1 和 T2 符合下列情况,则恶意调用方可以使用类型 T1 绕过用于保护 T2 的隐式的完全信任继承要求:
- T1 是在具有 APTCA 属性的完全受信任的程序集中声明的公共类型。 
- T1 继承自其程序集之外的类型 T2。 
- T2 的程序集没有 APTCA 属性,因此不应该由部分信任的程序集中的类型继承。 
部分信任的类型 X 可以从 T1 继承,后者赋予前者访问在 T2 中声明的继承成员的权限。由于 T2 没有 APTCA 属性,因此,其直接派生类型 (T1) 必须满足针对完全信任的继承要求;T1 具有完全信任,因此满足该检查。安全风险来自于:X 并不参与满足继承要求(保护 T2 不会被不受信任的子类继承)的过程。出于该原因,具有 APTCA 属性的类型不能扩展没有该属性的类型。
另一个安全问题(可能是更常见的问题)是:由于程序员的错误,派生类型 (T1) 会公开要求完全信任的类型 (T2) 中的受保护成员。发生这种情况时,不受信任的调用方能够访问到仅供完全受信任类型使用的信息。
如何修复冲突
如果冲突报告的类型在不要求 APTCA 属性的程序集中,请移除该类型。
如果要求 APTCA 属性,请向类型添加一个针对完全信任的继承要求。这样可以避免通过不受信任的类型进行继承。
可以通过将 APTCA 属性添加到由冲突报告的基类型的程序集来解决冲突。要执行该操作,必须首先对程序集中的所有代码以及依赖该程序集的所有代码进行严格的安全审查。
何时禁止显示警告
要安全地禁止显示此规则发出的警告,必须确保由您的类型公开的受保护成员不直接或间接地允许不受信任的调用方访问可通过破坏性方式使用的敏感信息、操作或资源。
示例
下面的示例使用两个程序集和一个测试应用程序来阐释该规则检测到的安全漏洞。第一个程序集没有 APTCA 属性,不应由部分受信任的类型继承(由前面讨论的 T2 表示)。
using System;
using System.Security;
using System.Security.Permissions;
using System.Reflection;
// This code is compiled into a strong-named assembly
// that requires full trust. 
namespace AptcaTestLibrary
{
   public class ClassRequiringFullTrustWhenInherited
   {
      // This field should be overridable by fully trusted derived types.
      protected static string location = "shady glen";
      // A trusted type can see the data, but cannot change it.
      public virtual string TrustedLocation 
      {
         get 
         {
            return location;
         }
      }
   }
}
第二个程序集(由前面讨论的 T1 表示)是完全受信任的,允许部分受信任的调用方。
using System;
using System.Security;
using System.Security.Permissions;
using System.Reflection;
// This class is compiled into an assembly that executes with full 
// trust and allows partially trusted callers. 
// Violates rule: AptcaTypesShouldOnlyExtendAptcaBaseTypes.
namespace AptcaTestLibrary
{
   public class InheritAClassRequiringFullTrust: 
      ClassRequiringFullTrustWhenInherited
   {
      private DateTime meetingDay = DateTime.Parse("February 22 2003");
      public override string ToString() 
      {
         // Another error:
         // This method gives untrusted callers the value 
         // of TrustedLocation. This information should 
         // only be seen by trusted callers.
         string s = String.Format(
            "Meet at the {0} {1}!", 
            this.TrustedLocation, meetingDay.ToString());
         return s;
      }
   }
}
由前面讨论的 X 表示的测试类型位于部分受信任的程序集中。
using System;
using AptcaTestLibrary;
// If this test application is run from the local machine, 
//  it gets full trust by default.
// Remove full trust.
[assembly: System.Security.Permissions.PermissionSetAttribute(
   System.Security.Permissions.SecurityAction.RequestRefuse, Name = "FullTrust")]
namespace TestSecLibrary
{
    class InheritFromAFullTrustDecendent : ClassRequiringFullTrust
    {
        public InheritFromAFullTrustDecendent()
        {
            // This constructor maliciously overwrites the protected 
            // static member in the fully trusted class.
            // Trusted types will now get the wrong information from 
            // the TrustedLocation property.
            InheritFromAFullTrustDecendent.location = "sunny meadow";
        }
        public override string ToString()
        {
            return InheritFromAFullTrustDecendent.location;
        }
    }
    class TestApctaInheritRule
    {
        public static void Main()
        {
            ClassRequiringFullTrust iclass =
               new ClassRequiringFullTrust();
            Console.WriteLine(iclass.ToString());
            // You cannot create a type that inherits from the full trust type
            // directly, but you can create a type that inherits from 
            // the APTCA type which in turn inherits from the full trust type.
            InheritFromAFullTrustDecendent inherit =
               new InheritFromAFullTrustDecendent();
            //Show the inherited protected member has changed.
            Console.WriteLine("From Test: {0}", inherit.ToString());
            // Trusted types now get the wrong information from 
            // the TrustedLocation property.
            Console.WriteLine(iclass.ToString());
        }
    }
}
该示例产生下面的输出。
Meet at the shady glen 2/22/2003 12:00:00 AM!
From Test: sunny meadow
Meet at the sunny meadow 2/22/2003 12:00:00 AM!
相关规则
请参见
概念
标有 AllowPartiallyTrustedCallersAttribute 的 .NET Framework 程序集