Поделиться через


CA2117: APTCA-типы должны расширять только базовые APTCA-типы

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());
        }
    }
}

После выполнения примера получается следующий результат.

      

Связанные правила

CA2116: методы APTCA должны вызывать только методы APTCA

См. также

Основные понятия

Правила написания безопасного кода

Сборки .NET Framework, вызываемые частично доверенным кодом

Использование библиотек из не вполне надежного кода

Требования наследования