CA2117 : Les types APTCA doivent uniquement étendre des types de base APTCA
TypeName |
AptcaTypesShouldOnlyExtendAptcaBaseTypes |
CheckId |
CA2117 |
Catégorie |
Microsoft.Security |
Modification avec rupture |
Oui |
Cause
Un type public ou protégé dans un assembly doté de l'attribut System.Security.AllowPartiallyTrustedCallersAttribute hérite d'un type déclaré présent dans un assembly dépourvu de l'attribut.
Description de la règle
Par défaut, des types publics ou protégés placés dans des assemblys présentant des noms forts sont implicitement protégés par un Demandes d'héritage dans le cadre confiance totale. Les assemblys dotés de noms forts marqués de l'attribut AllowPartiallyTrustedCallersAttribute (APTCA) n'ont pas cette protection. L'attribut désactive la demande d'héritage. Les types exposés sont alors déclarés dans l'assembly pouvant être hérité par des types dépourvus de confiance totale.
Lorsque l'attribut APTCA est présent sur un assembly doté d'une confiance totale et lorsqu'un type présent dans l'assembly hérite d'un type qui n'autorise pas les appelants partiellement approuvés, une exploitation de la sécurité devient possible. Si deux types T1 et T2 satisfont les conditions suivantes, des appelants malveillants peuvent utiliser le type T1 pour contourner la demande d'héritage de confiance totale implicite qui protège le type T2 :
T1 est un type public déclaré dans un assembly doté d'une confiance totale et de l'attribut APTCA.
T1 hérite d'un type T2 présent hors de son assembly.
L'assembly de T2 est dépourvu d'attribut APTCA ; par conséquent, les types présents dans des assemblys dotés d'une confiance partielle ne doivent pas pouvoir en hériter.
Un type X doté d'une confiance partielle peut hériter de T1, qui lui donne alors accès aux membres hérités déclarés dans T2. Sachant que T2 est dépourvu d'attribut APTCA, son type dérivé immédiat (T1) doit satisfaire une demande d'héritage pour la confiance totale ; T1 dispose d'une confiance totale et, par conséquent, satisfait ce contrôle. En termes de sécurité, le problème tient dans ce que X ne contribue pas à satisfaire la demande d'héritage qui protège T2 d'un sous-classement non approuvé. Pour cette raison, les types dotés de l'attribut APTCA ne doivent étendre aucun type dépourvu de l'attribut.
Un autre problème de sécurité, probablement plus répandu, tient dans ce que le type dérivé (T1) peut, par le biais d'une erreur du programmeur, exposer des membres protégés du type qui requiert la confiance totale (T2). Lorsque cette situation se produit, les appelants non approuvés ont accès à des informations qui ne doivent être disponibles qu'aux types dotés d'une confiance totale.
Comment corriger les violations
Si le type rapporté par l'infraction se trouve dans un assembly qui ne requiert pas l'attribut APTCA, supprimez-le.
Si l'attribut APTCA est requis, ajoutez au type une demande d'héritage pour la confiance totale. Ce procédé permet de se protéger contre l'héritage par les types non approuvés.
Il est possible de corriger une infraction en ajoutant l'attribut APTCA aux assemblys des types de base rapportés par celle-ci. Ne le faites pas sans procéder en premier lieu à une révision scrupuleuse de la sécurité de l'ensemble du code des assemblys et tout code qui dépend de ces derniers.
Quand supprimer les avertissements
Pour supprimer sans risque un avertissement de cette règle, vous devez vous assurer que les membres protégés exposés par votre type ne donnent pas, directement ou indirectement, à des appelants non approuvés un accès à des informations, des opérations ou des ressources sensibles, susceptibles d'être utilisées de façon destructrice.
Exemple
L'exemple suivant utilise deux assemblys et une application de test pour illustrer la faille de sécurité détectée par cette règle. Le premier assembly ne dispose pas de l'attribut APTCA et ne doit pas pouvoir être hérité par des types dotés d'une confiance partielle (représentés par T2 dans l'exposé précédent).
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 second assembly, représenté par T1 dans l'exposé précédent, est doté d'une confiance totale et autorise des appelants partiellement approuvés.
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 l'exposé précédent, se trouve dans un assembly doté d'une confiance partielle.
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 génère la sortie suivante :
Règles connexes
CA2116 : Les méthodes APTCA doivent uniquement appeler des méthodes APTCA
Voir aussi
Concepts
Instructions de codage sécurisé
Assemblys .NET Framework pouvant être appelés par le code d'un niveau de confiance partiel
Utilisation de bibliothèques à partir de code d'un niveau de confiance partiel