Condividi tramite


CA2117: I tipi APTCA devono estendere solo tipi di base APTCA

TypeName

AptcaTypesShouldOnlyExtendAptcaBaseTypes

CheckId

CA2117

Category

Microsoft.Security

Breaking Change

Breaking

Causa

Un tipo pubblico o protetto in un assembly con l'attributo System.Security.AllowPartiallyTrustedCallersAttribute eredita da un tipo dichiarato in un assembly che non presenta l'attributo.

Descrizione della regola

Per impostazione predefinita, i tipi pubblici o protetti in assembly con nomi sicuri sono protetti in modo implicito da Richieste di ereditarietà per l'attendibilità totale. Gli assembly con nomi sicuri contrassegnati con l'attributo AllowPartiallyTrustedCallersAttribute (APTCA) non presentano questa sicurezza. L'attributo disabilita la richiesta di ereditarietà. In questo modo i tipi esposti dichiarati nell'assembly vengono resi ereditabili da tipi che non presentano l'attendibilità totale.

Quando l'attributo APTCA è presente su un assembly totalmente attendibile e un tipo nell'assembly eredita da un tipo che non consente chiamanti parzialmente attendibili, è possibile che si verifichi una violazione della sicurezza. Se due tipi T1 e T2 soddisfano le seguenti condizioni, i chiamanti malintenzionati possono utilizzare il tipo T1 per ignorare la richiesta di ereditarietà con attendibilità totale implicita che protegge T2:

  • T1 è un tipo pubblico dichiarato in un assembly totalmente attendibile che presenta l'attributo APTCA.

  • T1 eredita da un tipo T2 al di fuori del relativo assembly.

  • L'assembly di T2 non presenta l'attributo APTCA e pertanto non è ereditabile da tipi in assembly parzialmente attendibili.

Un tipo parzialmente attendibile X può ereditare da T1 e ottenere pertanto accesso a membri ereditati dichiarati in T2. Poiché T2 non presenta l'attributo APTCA, il relativo tipo derivato immediato (T1) deve soddisfare una richiesta di ereditarietà per l'attendibilità totale; T1 presenta attendibilità totale e pertanto soddisfa questo controllo. Il rischio di sicurezza è dovuto al fatto che X non partecipa nel soddisfare la richiesta di ereditarietà che protegge T2 dalle sottoclassi non attendibili. Per questo motivo, i tipi con l'attributo APTCA non devono estendere tipi privi di questo attributo.

Un altro problema di sicurezza, forse più comune, è costituito dal fatto che il tipo derivato (T1) può, a causa di un errore del programmatore, esporre membri protetti dal tipo che richiede attendibilità totale (T2). Quando si verifica questa situazione, i chiamanti non attendibili possono ottenere accesso a informazioni che dovrebbero essere disponibili solo a tipi completamente attendibili.

Come correggere le violazioni

Se il tipo segnalato dalla violazione si trova in un assembly che non richiede l'attributo APTCA, rimuoverlo.

Se l'attributo APTCA è necessario, aggiungere una richiesta di ereditarietà per l'attendibilità totale al tipo come protezione dall'ereditarietà da parte di tipi non attendibili.

È possibile correggere una violazione aggiungendo l'attributo APTCA agli assembly dei tipi di base segnalati dalla violazione. Non eseguire questa operazione senza aver precedentemente effettuato una revisione accurata della sicurezza di tutto il codice negli assembly e di tutto il codice che dipende dagli assembly.

Esclusione di avvisi

Affinché l'esclusione di un avviso da questa regola sia sicura, è necessario assicurarsi che i membri protetti esposti dal tipo non consentano direttamente o indirettamente a chiamanti non attendibili di accedere a informazioni, operazioni o risorse riservate che possano essere utilizzate in modo distruttivo.

Esempio

Nell'esempio riportato di seguito vengono utilizzati due assembly e un'applicazione di test per illustrare la vulnerabilità della sicurezza rilevata da questa regola. Il primo assembly non presenta l'attributo APTCA e non deve essere ereditabile da tipi parzialmente attendibili (rappresentato da T2 nella spiegazione precedente).

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

Il secondo assembly, rappresentato da T1 nella spiegazione precedente, è totalmente attendibile e consente l'accesso a chiamanti parzialmente attendibili.

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

Il tipo di test, rappresentato da X nella spiegazione precedente, è contenuto in un assembly parzialmente attendibile.

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

Questo esempio produce l'output che segue.

      

Regole correlate

CA2116: I metodi APTCA devono chiamare solo metodi APTCA

Vedere anche

Concetti

Linee guida per la generazione di codice sicuro

Assembly .NET Framework contrassegnati da AllowPartiallyTrustedCallersAttribute

Utilizzo di librerie da codice parzialmente attendibile

Richieste di ereditarietà