CA2118 : Vérifier l'utilisation de SuppressUnmanagedCodeSecurityAttribute

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

Cause

Un type ou membre public ou protégé a l’attribut System.Security.SuppressUnmanagedCodeSecurityAttribute.

Notes

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

Description de la règle

SuppressUnmanagedCodeSecurityAttribute modifie le comportement du système de sécurité par défaut pour les membres qui exécutent du code non managé à l’aide de l’interopérabilité COM ou de l’appel de plateforme. En règle générale, le système effectue une autorisation de données et de modélisation pour le code non managé. Cette demande se produit au moment de l’exécution pour chaque appel du membre et vérifie chaque appelant dans la pile des appels pour obtenir l’autorisation. Lorsque l’attribut est présent, le système effectue une demande de liaison pour l’autorisation : les autorisations de l’appelant immédiat sont vérifiées lorsque l’appelant est compilé JIT.

Cet attribut est essentiellement utilisé pour accroître les performances ; toutefois, les gains de performance s’accompagnent de risques substantiels pour la sécurité. Si vous placez l’attribut sur les membres publics qui appellent des méthodes natives, les appelants dans la pile des appels (autres que l’appelant immédiat) n’ont pas besoin d’autorisation de code non managé pour exécuter du code non managé. Selon les actions et la gestion des entrées du membre public, il peut permettre aux appelants non fiables d’accéder aux fonctionnalités normalement limitées au code fiable.

.NET s’appuie sur des contrôles de sécurité pour empêcher les appelants d’accéder directement à l’espace d’adressage du processus actuel. Étant donné que cet attribut contourne la sécurité normale, votre code constitue une menace grave s’il peut être utilisé pour lire ou écrire dans la mémoire du processus. Notez que le risque n’est pas limité aux méthodes qui fournissent intentionnellement l’accès à la mémoire du processus; il est également présent dans n’importe quel scénario où le code malveillant peut obtenir l’accès par n’importe quel moyen, par exemple, en fournissant des entrées surprenantes, incorrectes ou non valides.

La stratégie de sécurité par défaut n’accorde pas l’autorisation de code non managé à un assembly, sauf si elle s’exécute à partir de l’ordinateur local ou est membre de l’un des groupes suivants :

  • Groupe de codes de zone Poste de travail

  • Groupe de codes de nom fort Microsoft

  • Groupe de codes de nom fort ECMA

Comment corriger les violations

Examinez soigneusement votre code pour vous assurer que cet attribut est absolument nécessaire. Si vous n’êtes pas familiarisé avec la sécurité du code managé ou si vous ne comprenez pas les implications liées à la sécurité lors de l’utilisation de cet attribut, supprimez-le de votre code. Si l’attribut est requis, vous devez vous assurer que les appelants ne peuvent pas utiliser votre code de manière malveillante. Si votre code n’est pas autorisé à exécuter du code non managé, cet attribut n’a aucun effet et doit être supprimé.

Quand supprimer les avertissements

Pour supprimer en toute sécurité un avertissement de cette règle, vous devez vous assurer que votre code ne fournit pas l’accès aux opérations natives ou aux ressources qui peuvent être utilisées de manière destructrice aux appelants.

Exemple 1

L'exemple suivant enfreint cette règle.

using System.Security;

// These two classes are identical
// except for the location of the attribute.

namespace SecurityRulesLibrary
{
    public class MyBadMemberClass
   {
      [SuppressUnmanagedCodeSecurityAttribute()]
      public void DoWork()
      {
         FormatHardDisk();
      }

      void FormatHardDisk()
      {
         // Code that calls unmanaged code.
      }
   }

   [SuppressUnmanagedCodeSecurityAttribute()]
   public class MyBadTypeClass
   {
      public void DoWork()
      {
         FormatHardDisk();
      }

      void FormatHardDisk()
      {
         // Code that calls unmanaged code.
      }
   }
}

Exemple 2

Dans l’exemple suivant, la méthode DoWork fournit un chemin de code accessible publiquement à la méthode d’appel de plateforme FormatHardDisk.

using System.Security;
using System.Runtime.InteropServices;

namespace SecurityRulesLibrary
{
   public class SuppressIsOnPlatformInvoke
   {
      // The DoWork method is public and provides unsecured access
      // to the platform invoke method FormatHardDisk.
      [SuppressUnmanagedCodeSecurityAttribute()]
      [DllImport("native.dll")]

      private static extern void FormatHardDisk();
      public void DoWork()
      {
         FormatHardDisk();
      }
   }

   // Having the attribute on the type also violates the rule.
   [SuppressUnmanagedCodeSecurityAttribute()]
   public class SuppressIsOnType
   {
      [DllImport("native.dll")]

      private static extern void FormatHardDisk();
      public void DoWork()
      {
         FormatHardDisk();
      }
   }
}

Exemple 3

Dans l’exemple suivant, la méthode DoDangerousThing publique provoque une violation. Pour résoudre la violation, DoDangerousThing doit être privé et l’accès à celui-ci doit se faire via une méthode publique sécurisée par une demande de sécurité, comme illustré par la méthode DoWork.

using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;

namespace SecurityRulesLibrary
{
   [SuppressUnmanagedCodeSecurityAttribute()]
   public class BadTypeWithPublicPInvokeAndSuppress
   {
      [DllImport("native.dll")]

      public static extern void DoDangerousThing();
      public void DoWork()
      {
         // Note that because DoDangerousThing is public, this 
         // security check does not resolve the violation.
         // This only checks callers that go through DoWork().
         SecurityPermission secPerm = new SecurityPermission(
            SecurityPermissionFlag.ControlPolicy | 
            SecurityPermissionFlag.ControlEvidence
         );
         secPerm.Demand();
         DoDangerousThing();
      }
   }
}

Voir aussi