CA2117 : Les types APTCA doivent uniquement étendre des types de base APTCA

Élément Valeur
ID de la règle CA2117
Category Microsoft.Security
Modification avec rupture Rupture

Cause

Un type public ou protégé dans un assembly avec l’attribut System.Security.AllowPartiallyTrustedCallersAttribute hérite d’un type déclaré dans un assembly qui n’a pas l’attribut.

Notes

Cette règle est déconseillée. Pour plus d’informations, consultez Règles dépréciées.

Description de la règle

Par défaut, les types publics ou protégés dans les assemblys portant des noms forts sont implicitement protégés par un InheritanceDemand à des fins de confiance totale. Les assemblys aux noms forts marqués avec l’attribut AllowPartiallyTrustedCallersAttribute (APTCA) ne bénéficient pas de cette protection. L’attribut désactive la demande d’héritage. Les types exposés déclarés dans un assembly sans demande d’héritage peuvent être hérités par des types qui n’ont pas une confiance totale.

Quand l’attribut APTCA est présent dans un assembly entièrement fiable et qu’un type présent dans l’assembly hérite d’un type qui n’autorise pas les appelants partiellement fiables, il en résulte une faille de sécurité dont l’exploitation est possible. Si deux types T1 et T2 remplissent les conditions suivantes, les appelants malveillants peuvent utiliser le type T1 pour contourner la demande implicite d’héritage de confiance totale qui protège T2 :

  • T1 est un type public déclaré dans un assembly entièrement fiable qui a l’attribut APTCA.

  • T1 hérite d’un type T2 en dehors de son assembly.

  • L’assembly de T2 n’a pas l’attribut APTCA et il ne doit donc pas être hérité par des types dans des assemblys partiellement fiables.

Un type X partiellement fiable peut hériter de T1, ce qui lui donne accès aux membres hérités déclarés dans T2. Étant donné que T2 n’a pas l’attribut APTCA, son type dérivé immédiat (T1) doit satisfaire à une demande d’héritage à des fins de confiance totale ; T1 a une confiance totale et satisfait donc à cette vérification. Le risque de sécurité est dû au fait que X ne participe pas à la satisfaction de la demande d’héritage qui protège T2 contre les sous-classes non approuvées. C’est pourquoi les types avec l’attribut APTCA ne doivent pas étendre des types qui n’ont pas l’attribut.

Un autre problème de sécurité, peut-être plus courant, est que le type dérivé (T1) peut, par erreur du programmeur, exposer les membres protégés du type qui nécessite une confiance totale (T2). Quand cette exposition se produit, les appelants non approuvés ont accès à des informations qui doivent être disponibles uniquement pour les types entièrement fiables.

Comment corriger les violations

Si le type signalé par la violation se trouve dans un assembly qui ne nécessite pas l’attribut APTCA, supprimez-le.

Si l’attribut APTCA est nécessaire, ajoutez une demande d’héritage de confiance totale au type. La demande d’héritage est une protection contre l’héritage par des types non approuvés.

Il est possible de corriger une violation en ajoutant l’attribut APTCA aux assemblys des types de base signalés par la violation. Ne le faites pas sans effectuer d’abord une révision intensive de la sécurité de tout le code dans les assemblys et de tout le code qui dépend des assemblys.

Quand supprimer les avertissements

Pour supprimer en toute sécurité un avertissement de cette règle, vous devez veiller à ce que les membres protégés exposés par votre type n’autorisent pas directement ou indirectement les appelants non approuvés à accéder à des informations sensibles, opérations ou ressources pouvant être utilisées de manière destructrice.

Exemple

L’exemple suivant utilise deux assemblys et une application de test pour illustrer la vulnérabilité de sécurité détectée par cette règle. Le premier assembly n’a pas l’attribut APTCA et ne doit pas pouvoir être hérité par des types partiellement fiables (représentés par T2 dans la discussion précédente).

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

Le deuxième assembly, représenté par T1 dans la discussion précédente, est entièrement fiable et autorise les appelants partiellement fiables.

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

Le type de test, représenté par X dans la discussion précédente, se trouve dans un assembly partiellement fiable.

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

Cet exemple produit la sortie suivante :

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!

CA2116 : Les méthodes APTCA doivent uniquement appeler des méthodes APTCA

Voir aussi