Ce sujet n'a pas encore été évalué - Évaluez ce sujet

Création d'assemblys sécurisés

Dernière mise à jour le 31 août 2004
Sur cette page

Dans ce module Dans ce module
Objectifs Objectifs
S'applique à S'applique à
Menaces et contre-mesures Menaces et contre-mesures
Code privilégié Code privilégié
Éléments à prendre en compte pour la conception de l'assembly Éléments à prendre en compte pour la conception de l'assembly
Éléments à prendre en compte pour la conception de classes Éléments à prendre en compte pour la conception de classes
Noms forts Noms forts
Autorisation Autorisation
Gestion des exceptions Gestion des exceptions
E/S sur fichier E/S sur fichier
Journal d'événements Journal d'événements
Registre Registre
Accès aux données Accès aux données
Code non géré Code non géré
Délégués Délégués
Sérialisation Sérialisation
Thread Thread
Réflexion Réflexion
Obscurcissement Obscurcissement
Cryptographie Cryptographie
Résumé Résumé
Ressources supplémentaires Ressources supplémentaires

Dans ce module

Les assemblys sont les blocs constitutifs fondamentaux des applications .NET Framework et représentent l'unité de déploiement, de contrôle de version et de réutilisation. Ils sont également l'unité de confiance de la sécurité d'accès au code (tout le code d'un assembly bénéficie d'un niveau de confiance identique).

Le module commence par répertorier et expliquer les menaces courantes pour les assemblys et les contre-mesures associées. Il fournit ensuite une liste complète des zones de sécurité que vous devez prendre en compte pour améliorer la conception et l'implémentation de la sécurité de vos assemblys. Celle-ci comprend l'évaluation des éléments à prendre en compte pour le déploiement, le suivi des pratiques de programmation solides orientées objet, la protection de votre code contre les falsifications, le contrôle des informations au niveau du système interne pour qu'elles ne soient pas révélées à l'appelant et la limitation des personnes pouvant appeler votre code.

Objectifs

Ce module vous permettra d'effectuer les opérations suivantes :

  • améliorer la sécurité de vos assemblys avec des techniques de codage éprouvées et simples ;

  • réduire la surface d'attaque par le biais d'interfaces bien conçues et de techniques de programmation orientées objet solides ;

  • utiliser des noms forts pour protéger vos assemblys contre les falsifications ;

  • réduire les risques liés à l'appel d'un code non géré ;

  • écrire un code d'accès aux ressources sécurisé comprenant l'accès aux E/S sur fichier, au Registre, au journal d'événements, à la base de données et au réseau ;

  • savoir quelles contre-mesures appliquer pour faire face aux menaces courantes des assemblys, notamment l'élévation des privilèges, l'injection de code, la divulgation d'informations et la falsification.

S'applique à

Ce module s'applique aux produits et technologies suivants :

  • Microsoft Windows Server 2000 et 2003 ;

  • Microsoft .NET Framework 1.1 et ASP.NET 1.1.

Menaces et contre-mesures

En connaissant les menaces et les types courants d'attaques, vous pourrez identifier les contre-mesures appropriées et créer des assemblys plus robustes et plus sécurisés. Les principales menaces sont les suivantes :

  • accès non autorisé ou élévation de privilèges, ou les deux ;

  • injection de code ;

  • divulgation d'informations ;

  • falsification.

La figure 7.1 illustre ces principales menaces.

 Menaces au niveau de l'assembly

Figure 7.1
Menaces au niveau de l'assembly

Accès non autorisé ou élévation de privilèges, ou les deux

Le risque d'un accès non autorisé, qui peut conduire à une élévation des privilèges, est qu'un utilisateur non autorisé ou un code non autorisé peut appeler votre assembly pour exécuter des opérations privilégiées et accéder aux ressources restreintes.

Vulnérabilités

Les vulnérabilités pouvant conduire à un accès non autorisé ou à une élévation des privilèges sont les suivantes :

  • autorisation basée sur les rôles faible ou absente ;

  • types internes ou membres de type exposés par inadvertance ;

  • utilisation non sécurisée d'assertions de sécurité d'accès au code et de demandes de liaison ;

  • classes de base non scellées et non restreintes, ce qui permet d'en dériver n'importe quel code.

Attaques

Les attaques courantes sont les suivantes :

  • une attaque par leurre où un code malveillant accède à votre assembly via un assembly intermédiaire sécurisé pour ignorer les mécanismes d'autorisation ;

  • une attaque où un code malveillant ignore les contrôles d'accès en appelant directement les classes qui ne font pas partie de l'API publique de l'assembly.

Contre-mesures

Les contre-mesures que vous pouvez utiliser pour éviter un accès non autorisé et une élévation des privilèges sont les suivantes :

  • utiliser l'autorisation basée sur les rôles pour fournir des contrôles d'accès sur toutes les classes publiques et les membres des classes ;

  • restreindre la visibilité du type et du membre pour limiter les codes accessibles au public ;

  • mettre en sandbox le code privilégié et vérifier que le code appelant est autorisé avec les demandes d'autorisation appropriées ;

  • sceller les classes hors base ou restreindre l'héritage avec la sécurité d'accès au code.

Injection de code

Avec l'injection de code, un pirate exécute un code arbitraire en utilisant le contexte de sécurité au niveau du processus de votre assembly. Le risque est augmenté si votre assembly appelle un code non géré et si votre assembly s'exécute sous un compte privilégié.

Vulnérabilités

Les vulnérabilités pouvant conduire à une injection de code sont les suivantes :

  • validation de la saisie insuffisante, en particulier à l'endroit où votre assembly appelle un code non géré ;

  • acceptation de délégués à partir d'un code à confiance partielle ;

  • comptes de processus trop privilégiés.

Attaques

Les attaques par injection de code courantes sont les suivantes :

  • dépassement de capacité de la mémoire tampon ;

  • appel d'un délégué à partir d'une source non sécurisée.

Contre-mesures

Les contre-mesures que vous pouvez utiliser pour éviter l'injection de code sont les suivantes :

  • valider les paramètres de saisie ;

  • valider les données passées aux API non gérées ;

  • ne pas accepter de délégués de sources non approuvées ;

  • utiliser des délégués fortement typés et refuser toute autorisation avant d'avoir appelé le délégué ;

  • pour réduire encore le risque, exécuter des assemblys en utilisant les comptes les moins privilégiés.

Divulgation des informations

Les assemblys peuvent subir une divulgation d'informations s'ils dévoilent des données sensibles telles que des détails d'exception et des secrets en texte clair aux utilisateurs légitimes comme aux utilisateurs malveillants. Il est également plus facile de soumettre les instructions MSIL (Microsoft Intermediate Language) d'un assembly à un processus de rétroconception dans un code source que dans un code machine binaire. Cela représente une menace pour la propriété intellectuelle.

Vulnérabilités

Les vulnérabilités pouvant conduire à une divulgation des informations sont les suivantes :

  • gestion des exceptions faible ou informelle ;

  • secrets préprogrammés dans le code.

Attaques

Les attaques courantes sont les suivantes :

  • tentative de production d'erreurs en passant une saisie incorrecte dans l'assembly ;

  • utilisation d'ILDASM sur un assembly pour voler des secrets.

Contre-mesures

Les contre-mesures que vous pouvez utiliser pour éviter la divulgation des informations sont les suivantes :

  • validation solide de la saisie ;

  • gestion des exceptions structurée et renvoi des erreurs génériques au client ;

  • pas de stockage de secrets dans le code ;

  • outils d'obscurcissement pour déjouer les décompilateurs et protéger la propriété intellectuelle.

Falsification

Le risque de la falsification est que votre assembly soit modifié en altérant les instructions MSIL dans le fichier d'assembly DLL ou binaire.

Vulnérabilités

La principale vulnérabilité qui rend votre assembly vulnérable à la falsification est l'absence de signature de nom fort.

Attaques

Les attaques courantes sont les suivantes :

  • manipulation directe des instructions MSIL ;

  • rétroconception des instructions MSIL.

Contre-mesures

Pour contrer la menace de falsification, utilisez un nom fort pour signer l'assembly avec une clé privée. Lorsqu'un assembly signé est chargé, l'exécution du langage commun détecte si l'assembly a été modifié de quelque manière que ce soit et ne charge pas l'assembly s'il a été altéré.

Code privilégié

Lorsque vous concevez et créez des assemblys sécurisés, vous devez être capable d'identifier un code privilégié. Les implications sont importantes pour la sécurité d'accès au code. Un code privilégié est un code géré qui accède aux ressources sécurisées ou effectue d'autres opérations sensibles de sécurité telles que l'appel d'un code non géré, l'utilisation de la sérialisation ou l'utilisation de la réflexion. On parle de code privilégié parce qu'il doit bénéficier d'une autorisation accordée par la stratégie de sécurité d'accès au code pour fonctionner. Un code non privilégié requiert uniquement une autorisation d'exécution.

Ressources privilégiées

Les types de ressources pour lesquelles votre code requiert des autorisations de sécurité d'accès au code sont le système de fichiers, les bases de données, le Registre, le journal d'événements, les services Web, les sockets, les bases de données DNS, les services d'annuaire et les variables d'environnement.

Opérations privilégiées

Les autres opérations privilégiées pour lesquelles votre code requiert des autorisations de sécurité d'accès au code sont notamment l'appel d'un code non géré, l'utilisation de la sérialisation, l'utilisation de la réflexion, la création et le contrôle des domaines d'application, la création d'objets Principal et la manipulation de la stratégie de sécurité.

Pour plus d'informations sur les types spécifiques d'autorisations de sécurité d'accès au code requis pour accéder aux ressources et effectuer des opérations privilégiées, consultez la section « Code privilégié » du module 8 « La sécurité d'accès au code en pratique ».

Éléments à prendre en compte pour la conception de l'assembly

L'un des problèmes les plus significatifs à prendre en compte au moment de la conception est le niveau de confiance de l'environnement cible de votre assembly, qui a un impact sur les autorisations de sécurité d'accès au code accordées à votre code et au code qui appelle votre code. Celui-ci est déterminé par la stratégie de sécurité d'accès au code définie par l'administrateur, et il a un impact sur les types de ressources auxquelles votre code est autorisé à accéder et les autres opérations privilégiées qu'il peut effectuer.

Lorsque vous concevez votre assembly, vous devez effectuer les opérations suivantes :

  • identifier le code privilégié ;

  • identifier le niveau de confiance de votre environnement cible ;

  • mettre en sandbox le code hautement privilégié ;

  • concevoir votre interface publique.

Identification du code privilégié

Identifiez le code qui accède aux ressources sécurisées ou qui effectue des opérations sensibles de sécurité. Ce type de code requiert des autorisations d'accès au code spécifiques pour fonctionner.

Identification des ressources privilégiées

Identifiez les types de ressources auxquelles votre assembly doit accéder ; vous pourrez ainsi identifier tous les problèmes potentiels susceptibles de se produire si l'environnement dans lequel votre assembly s'exécute en dernier n'accorde pas les autorisations de sécurité d'accès au code pertinentes. Dans ce cas, vous serez obligé soit de mettre à jour la stratégie de sécurité d'accès au code de votre application si l'administrateur l'autorise, soit de mettre en sandbox votre code privilégié. Pour plus d'informations sur la mise en sandbox, consultez le module 9 « Utilisation de la sécurité d'accès au code avec ASP.NET ».

Identification des opérations privilégiées

Identifiez également toutes les opérations privilégiées devant être effectuées par votre assembly, de manière à savoir également quelles autorisations d'accès au code sont requises par votre code au moment de l'exécution.

Identification du niveau de confiance de votre environnement cible

L'environnement cible dans lequel votre assembly est installé est important car la stratégie de sécurité d'accès au code peut limiter les autorisations de votre assembly. Si, par exemple, votre assembly dépend de l'utilisation de OLE DB, il échouera dans n'importe quel environnement autre qu'un environnement de confiance totale.

Environnement de confiance totale

La confiance totale signifie que le code dispose d'un jeu d'autorisations de sécurité d'accès au code non restreint, qui lui permet d'accéder à tous les types de ressources et d'effectuer des opérations privilégiées, soumises à la sécurité du système d'exploitation. L'environnement de confiance totale est l'environnement par défaut d'une application Web et des assemblys installés sur un serveur Web qui la prennent en charge, mais ceci peut être modifié en configurant l'élément <trust> de l'application.

Environnement de confiance partielle

Un environnement de confiance partielle englobe tout ce qui ne bénéficie pas d'un niveau de confiance totale. .NET Framework intègre plusieurs niveaux de confiance prédéfinis que vous pouvez utiliser directement ou personnaliser pour répondre à vos exigences spécifiques de sécurité. Le niveau de confiance peut également être diminué par l'origine du code. Par exemple, le code d'un partage réseau bénéficie d'un niveau de confiance inférieur à celui du code d'un ordinateur local et sa capacité à effectuer des opérations privilégiées est par conséquent limitée.

Prise en charge des appelants de confiance partielle

Le risque d'un compromis de sécurité augmente considérablement si votre assembly prend en charge des appelants de confiance partielle (c'est-à-dire, un code ne bénéficiant pas d'une confiance totale). La sécurité d'accès au code dispose de protections supplémentaires pour réduire le risque. Pour obtenir d'autres instructions s'appliquant aux assemblys qui prennent en charge des appelants de confiance partielle, consultez le module 8 « La sécurité d'accès au code en pratique ». Sans programmation supplémentaire, votre code prend en charge des appelants de confiance partielle dans les deux situations suivantes :

  • votre assembly n'a pas de nom fort ;

  • votre assembly a un nom fort et intègre l'attribut de niveau assembly AllowPartiallyTrustedCallersAttribute (APTCA).

Pourquoi s'inquiéter de l'environnement cible ?

L'environnement de confiance dans lequel s'exécute votre assembly est important pour les raisons suivantes :

  • Un assembly de confiance partielle peut uniquement accéder à un jeu de ressources limité et effectuer un jeu d'opérations restreint, selon les autorisations de sécurité d'accès au code qui lui sont accordées par la stratégie de sécurité d'accès au code.

  • Un assembly de confiance partielle ne peut pas appeler un assembly avec nom fort à moins qu'il n'intègre l'attribut AllowPartiallyTrustedCallersAttribute.

  • Il se peut que d'autres assemblys de confiance partielle ne puissent pas appeler votre assembly parce qu'ils ne disposent pas des autorisations nécessaires. Les autorisations dont doit disposer un assembly appelant pour appeler votre assembly sont déterminées par les éléments suivants :

    • les types de ressources auxquelles accède votre assembly ;

    • les types d'opérations privilégiées que peut effectuer votre assembly.

Mise en sandbox d'un code hautement privilégié

Pour éviter d'accorder des autorisations puissantes à tout une application uniquement dans le but de répondre aux besoins de quelques méthodes qui effectuent des opérations privilégiées, mettez le code privilégié en sandbox et placez-le dans un assembly séparé. Un administrateur peut ainsi configurer la stratégie d'accès au code pour qu'elle accorde des autorisations étendues au code de l'assembly spécifique et non à toute l'application.

Par exemple, si votre application doit appeler un code non géré, mettez en sandbox les appels non gérés dans un assembly de wrappers. L'administrateur peut ainsi accorder une autorisation UnmanagedCodePermission à l'assembly de wrappers et non à toute l'application.

Remarque : la mise en sandbox requiert l'utilisation d'un assembly séparé et l'assertion des autorisations de sécurité pour éviter des parcours complets de la pile.

Pour plus d'informations sur la mise en sandbox des appels d'API non gérés, consultez la section « Code non géré » du module 8 « La sécurité d'accès au code en pratique ».

Conception de votre interface publique

Réfléchissez bien aux types et membres qui font partie de l'interface publique de votre assembly. Limitez la surface d'attaque de l'assembly en réduisant le nombre de points d'entrée et en utilisant une interface publique minime et bien conçue.

Éléments à prendre en compte pour la conception de classes

En plus d'utiliser une interface publique minime et bien définie, vous pouvez encore réduire la surface d'attaque de votre assembly en concevant des classes sécurisées. Les classes sécurisées se conforment aux principes de conception solide orientée objet, empêchent l'héritage lorsqu'il n'est pas requis et limitent les appelants et les codes autorisés à les appeler. Les recommandations suivantes vous permettent de concevoir des classes sécurisées :

  • restreindre la visibilité de la classe et du membre ;

  • sceller les classes hors base ;

  • restreindre les utilisateurs autorisés à appeler votre code ;

  • exposer les champs à l'aide des propriétés.

Restriction de la visibilité de la classe et du membre

Utilisez le modificateur d'accès public uniquement pour les types et les membres qui font partie de l'interface publique de l'assembly. La surface d'attaque est ainsi immédiatement réduite car le code peut uniquement accéder aux types publics en dehors de l'assembly. Tous les autres types et membres doivent être aussi restreints que possible. Utilisez le modificateur d'accès private partout où cela est possible. Utilisez protected uniquement si le membre doit être accessible aux classes dérivées et utilisez internal uniquement si le membre doit être accessible aux autres classes du même assembly.

Remarque : C# vous permet également de combiner protected et internal pour créer un membre protected internal afin de limiter l'accès à l'assembly en cours ou aux types dérivés.

Scellage des classes hors base

Si une classe n'est pas conçue comme une classe de base, empêchez l'héritage en utilisant le mot clé sealed comme indiqué dans l'échantillon de code suivant.

public sealed class NobodyDerivesFromMe
{}

Pour les classes de base, vous pouvez limiter les codes pouvant être dérivés de votre classe en utilisant des demandes d'héritage de la sécurité d'accès au code. Pour plus d'informations, consultez la section « Autorisation du code » du module 8 « La sécurité d'accès au code en pratique ».

Restriction des utilisateurs autorisés à appeler votre code

Annotez les classes et les méthodes avec des demandes d'autorisation principales déclaratives pour contrôler les utilisateurs autorisés à appeler vos classes et vos membres de classes. Dans l'exemple suivant, seuls les membres du groupe Windows spécifié peuvent accéder à la classe Orders. Un attribut de niveau classe tel que celui-ci s'applique à tous les membres de la classe. Les demandes d'autorisation principales déclaratives peuvent également être utilisées sur des méthodes individuelles. Les attributs de niveau méthode remplacent les attributs de niveau classe.

[PrincipalPermission(SecurityAction.Demand, 
                     Role=@"NomDomaine\GroupeWindows")]
public sealed class Orders()
{
}

Exposition des champs à l'aide des propriétés

Rendez tous les champs privés (private). Pour qu'une valeur de champ soit accessible aux types externes, utilisez une propriété de lecture seule ou de lecture/écriture. Les propriétés vous permettent d'ajouter des contraintes supplémentaires, telles que la validation de la saisie ou les demandes d'autorisation, comme le montre l'échantillon de code suivant.

public sealed class MyClass
{
  private string field; // la chaîne field est privée
  // Seuls les membres du groupe indiqué sont en mesure
  // d'accéder à cette rubrique publique
  [PrincipalPermission(SecurityAction.Demand, 
          Role=@"NomDomaine\GroupeWindows")]
  public string Field
  {
    get {
        return field;
    }
  }
}

Noms forts

Le nom fort d'un assembly se compose d'un nom, d'un numéro de version, et facultativement d'une culture, d'une clé publique (qui représente souvent votre organisation de développement) et d'une signature numérique. Vous pouvez voir les différents composants du nom fort en consultant Machine.config et en regardant comment un assembly avec nom fort est référencé.

L'exemple suivant montre comment l'assembly System.Web est référencé dans Machine.config. Dans cet exemple, l'attribut assembly montre le nom, la version, la culture et le jeton de clé publique, qui est une forme raccourcie de la clé publique.

<add assembly="System.Web, Version=1.0.5000.0, Culture=neutral, 
               PublicKeyToken=b03f5f7f11d50a3a" />

Donner ou non un nom fort à un assembly dépend de la manière dont vous souhaitez qu'il soit utilisé. Les principales raisons pour lesquelles vous pouvez souhaiter ajouter un nom fort dans un assembly sont les suivantes :

  • Vous souhaitez vous assurer qu'un code à confiance partielle ne pourra pas appeler votre assembly.
    L'exécution du langage commun empêche un code à confiance partielle d'appeler un assembly avec nom fort, en ajoutant des demandes de liaison pour le jeu d'autorisations FullTrust. Vous pouvez remplacer ce comportement en utilisant AllowPartiallyTrustedCallersAttribute (APTCA), mais utilisez-le avec précaution.

    Pour plus d'informations sur APTCA, consultez la section APTCA du module 8 « La sécurité d'accès au code en pratique ».

  • Cet assembly est conçu pour être partagé entre plusieurs applications.
    Dans ce cas, l'assembly doit être installé dans le cache de l'assembly global. Pour cela il faut un nom fort. Le cache de l'assembly global prend en charge le versioning côte à côte qui permet de lier différentes applications à différentes versions du même assembly.

  • Vous souhaitez utiliser le nom fort comme preuve de sécurité.
    La portion de clé publique du nom fort fournit une preuve cryptographique forte pour la sécurité d'accès au code. Vous pouvez utiliser le nom fort pour identifier de manière unique l'assembly lorsque vous configurez la stratégie de sécurité d'accès au code afin d'accorder des autorisations d'accès au code spécifiques à l'assembly. Les autres formes de preuve cryptographique forte incluent la signature Authenticode (si vous avez utilisé les certificats X.509 pour signer l'assembly) et le hachage d'un assembly.

    Remarque : la preuve Authenticode n'est pas chargée par l'hôte ASP.NET, ce qui signifie que vous ne pouvez pas l'utiliser pour mettre en œuvre une stratégie de sécurité pour les applications Web ASP.NET.

    Pour plus d'informations sur les types de preuve et sur la sécurité d'accès au code, consultez le module 8 « La sécurité d'accès au code en pratique ».

Avantages de sécurité des noms forts

Les noms forts fournissent un grand nombre d'avantages de sécurité en plus des avantages du versioning :

  • Les assemblys avec nom fort sont signés avec une signature numérique. L'assembly est ainsi protégé contre les modifications. Toute falsification arrête le processus de vérification qui se produit au moment du chargement de l'assembly. Une exception est générée et l'assembly n'est pas chargé.

  • Les assemblys avec nom fort ne peuvent pas être appelés par des codes à confiance partielle, à moins que vous n'ajoutiez spécifiquement AllowPartiallyTrustedCallersAttribute (APTCA.)

    Remarque : si vous n'utilisez pas APTCA, lisez le module 8 « La sécurité d'accès au code en pratique » pour obtenir des instructions supplémentaires sur la manière d'améliorer la sécurité de vos assemblys.

  • Les noms forts fournissent une preuve cryptographique forte pour l'évaluation de la stratégie de sécurité d'accès au code. Les administrateurs peuvent ainsi accorder des autorisations à des assemblys spécifiques. Cela permet également aux développeurs d'utiliser une autorisation StrongNameIdentityPermission pour restreindre les codes pouvant appeler un membre public ou pouvant être dérivés d'une classe non scellée.

Utilisation des noms forts

.NET Framework intègre l'utilitaire Sn.exe pour vous permettre d'ajouter un nom fort aux assemblys. Pour ce faire, vous n'avez pas besoin d'un certificat X.509.

  • Pour ajouter un nom fort dans un assembly

    1. Générez un fichier de clé dans le répertoire du projet de l'assembly en utilisant la commande suivante.

      sn.exe -k keypair.snk
      
    2. Ajoutez un attribut AssemblyKeyFile dans Assemblyinfo.cs pour référencer le fichier de clé généré, comme indiqué dans l'échantillon de code suivant.

      // Le fichier keypair est généralement placé dans le répertoire du projet
      [assembly: AssemblyKeyFile(@"..\..\keypair.snk")]

Temporisation de signature

Une bonne pratique de sécurité consiste à temporiser la signature de vos assemblys durant le développement de l'application. La clé publique est ainsi placée dans l'assembly, ce qui signifie qu'elle est disponible comme preuve de la stratégie de sécurité d'accès au code, mais l'assembly n'est pas signé, et n'est par conséquent pas encore protégé contre les falsifications. Du point de vue de la sécurité, la temporisation de signature présente deux avantages principaux :

  • La clé publique utilisée pour signer l'assembly et créer sa signature numérique est conservée en sécurité dans un emplacement central. La clé est accessible uniquement par quelques membres de confiance du personnel. Par conséquent, les chances pour que la clé publique soit compromise sont considérablement réduites.

  • Une clé publique unique, pouvant représenter l'organisation de développement ou l'éditeur du logiciel, est utilisée par tous les membres de l'équipe de développement, plutôt que d'obliger chaque développeur à utiliser sa propre paire de clés publique/privée, généralement générée par la commande sn –k.

  • Pour créer un fichier de clé publique pour la temporisation de signature

    Cette procédure est effectuée par l'autorité de signature pour créer un fichier de clé publique pouvant être utilisé par les développeurs pour temporiser la signature de leurs assemblys.

    1. Créez une paire de clés pour votre organisation.

      sn.exe-k keypair.snk
      
    2. Extrayez la clé publique du fichier de paire de clés.

      sn-p keypair.snk publickey.snk
      
    3. Sécurisez Keypair.snk, qui contient les clés publique et privée. Par exemple, placez-le sur une disquette ou un CD et mettez-le physiquement en sécurité.

    4. Mettez Publickey.snk à la disposition de tous les développeurs. Placez-le par exemple sur un partage réseau.

  • Pour temporiser la signature d'un assembly

    Cette procédure est effectuée par les développeurs.

    1. Ajoutez un attribut de niveau assembly pour référencer le fichier de clé qui contient uniquement la clé publique.

      // Le fichier keypair est généralement placé dans le répertoire du projet
      [assembly: AssemblyKeyFile(@"..\..\publickey.snk")]
      
    2. Ajoutez l'attribut suivant pour indiquer la temporisation de signature.

      [assembly: AssemblyDelaySign(true)]
      
    3. Le processus de temporisation de signature et l'absence de signature dans l'assembly conduiront la vérification de l'assembly à s'arrêter au moment du chargement. Pour éviter cela, utilisez les commandes suivantes sur les ordinateurs de développement et de test.

      • Pour désactiver la vérification d'un assembly spécifique, utilisez la commande suivante.

        sn -Vr assembly.dll
        
      • Pour désactiver la vérification de tous les assemblys avec une clé publique particulière, utilisez la commande suivante.

        sn -Vr *,publickeytoken
        
      • Pour extraire la clé publique et le jeton de clé (un hachage tronqué de la clé publique), utilisez la commande suivante.

        sn -Tp assembly.dll
        

        Remarque : utilisez un commutateur –T majuscule.

    4. Pour terminer complètement le processus de signature et créer une signature numérique afin de protéger l'assembly contre les falsifications, exécutez la commande suivante. Cette commande requiert la clé publique et par conséquent l'opération est normalement effectuée dans le cadre du processus formel de création/publication.

      sn-r assembly.dll keypair.snk

ASP.NET et les noms forts

Au moment où nous écrivons ce guide, il n'est pas possible d'utiliser un nom fort pour un assembly de page Web ASP.NET en raison de sa compilation dynamique. Même si vous utilisez un fichier code-behind pour créer un assembly précompilé contenant le code d'implémentation de la classe de votre page, ASP.NET crée et compile dynamiquement une classe contenant les éléments virtuels de votre page. Cette classe est dérivée de la classe de votre page, ce qui signifie une fois de plus que vous ne pouvez pas utiliser des noms forts.

Remarque : vous pouvez ajouter un nom fort à tout autre assembly appelé par le code de votre page Web, par exemple, un assembly contenant un code d'accès aux ressources, aux données et à la logique métier, mais l'assembly doit être placé dans le cache de l'assembly global.

Exigences du cache de l'assembly global

Tout assembly avec nom fort appelé par une application Web ASP.NET configurée avec une confiance partielle doit être installé dans le cache de l'assembly global. C'est parce que l'hôte ASP.NET charge tous les assemblys avec nom fort comme étant indépendants du domaine.

Le code d'un assembly indépendant du domaine est partagé par tous les domaines d'application dans le processus ASP.NET. Ceci crée des problèmes lorsqu'un seul assembly avec nom fort est utilisé par plusieurs applications Web et que chaque application accorde différentes autorisations ou que l'autorisation varie entre les redémarrages de domaine d'application. Dans cette situation, il se peut que le message d'erreur suivant apparaisse : « Le jeu d'autorisations de sécurité de l'assembly <assembly>.dll n'est pas compatible entre les domaines de l'application. »

Pour éviter cette erreur, vous devez placer les assemblys avec nom fort dans le cache de l'assembly global et non dans le répertoire \bin privé de l'application.

Authenticode contre noms forts

Authenticode et les noms forts fournissent deux moyens différents de signer numériquement un assembly. Authenticode vous permet de signer un assembly à l'aide d'un certificat X.509. Pour ce faire, vous utilisez l'utilitaire Signcode.exe, qui ajoute la partie clé publique d'un certificat X.509 complet à l'assembly. Ceci garantit l'approbation à travers les chaînes et les autorités de certification. Avec Authenticode (contrairement aux noms forts), l'implémentation de l'approbation de l'éditeur est complexe et implique une communication réseau durant la vérification de l'identité de l'éditeur.

Les signatures Authenticode et les noms forts ont été développés pour résoudre des problèmes séparés et vous ne devez pas les confondre. À savoir en particulier :

  • un nom fort identifie uniquement un assembly ;

  • une signature Authenticode identifie uniquement un éditeur de code.
    Les signatures Authenticode doivent être utilisées pour un code mobile, tel que les contrôles et les exécutables téléchargés via Internet Explorer, afin d'assurer l'approbation et l'intégrité de l'éditeur.

Vous pouvez configurer la stratégie de sécurité d'accès au code (CAS) à l'aide de noms forts et de signatures Authenticode pour accorder des autorisations à des assemblys spécifiques. Cependant, l'objet de preuve Éditeur, obtenu à partir d'une signature Authenticode est uniquement créé par l'hôte Internet Explorer et non par l'hôte ASP.NET. Par conséquent, côté serveur, vous ne pouvez pas utiliser une signature Authenticode pour identifier un assembly spécifique (via un groupe de codes). Utilisez plutôt des noms forts.

Pour plus d'informations sur CAS, la stratégie CAS et les groupes de codes, consultez le module 8 « La sécurité d'accès au code en pratique ».

Le tableau 7.1 compare les fonctionnalités des noms forts et des signatures Authenticode.

Tableau 7.1 : Comparaison des noms forts et des signatures Authenticode

Fonctionnalité

Nom fort

Authenticode

Identification unique de l'assembly

Oui

Non

Identification unique de l'éditeur

Pas nécessairement. Cela dépend si le développeur a utilisé une clé publique pour représenter l'éditeur.

Oui

La clé publique de l'éditeur ne peut pas être refusée

Non

Oui

Versioning

Oui

Non

Espace de noms et nom de type uniques

Oui

Non

Intégrité (vérifie que l'assembly n'a pas été falsifié)

Oui

Oui

Preuve utilisée comme entrée dans la stratégie CAS

Oui

Hôte IE – Oui.
Hôte ASP.NET – Non

Saisie de l'utilisateur requise pour la décision d'approbation

Non

Oui (boîte de dialogue en incrustation)

Autorisation

Vous pouvez utiliser deux types d'autorisation dans vos assemblys pour contrôler l'accès aux classes et aux membres des classes :

  • L'autorisation basée sur les rôles pour autoriser l'accès en fonction de l'identité et de l'appartenance du rôle de l'utilisateur. Lorsque vous utilisez l'autorisation basée sur les rôles dans des assemblys qui font partie d'une application Web ASP.NET ou d'un service Web, vous autorisez l'identité représentée par un objet IPrincipal joint à la requête Web en cours et disponible via Thread.CurrentPrincipal et HttpContext.Current.User. Cette identité est soit l'identité de l'utilisateur final authentifié, soit l'identité d'un utilisateur Internet anonyme. Pour plus d'informations sur l'utilisation d'une autorisation basée sur l'entité dans des applications Web, consultez la section « Autorisation » du module 10 « Création de pages Web et de contrôles ASP.NET sécurisés ».

  • La sécurité d'accès au code pour autoriser un code appelant, en se basant sur une preuve, telle que le nom fort ou l'emplacement d'un assembly. Pour plus d'informations, consultez la section « Autorisation » du module 8 « La sécurité d'accès au code en pratique ».

Gestion des exceptions

Ne révélez pas les détails d'implémentation de votre application dans les messages d'exception renvoyés au client. Cette information peut permettre aux utilisateurs malveillants de planifier des attaques de votre application. Pour assurer une gestion des exceptions correcte, suivez les instructions suivantes :

  • utiliser une gestion des exceptions structurée ;

  • ne pas enregistrer les données sensibles ;

  • ne pas révéler les informations sensibles sur le système ou l'application ;

  • prendre en compte les problèmes de filtre d'exceptions ;

  • prendre en compte un cadre de gestion des exceptions.

Utiliser une gestion des exceptions structurée

Microsoft Visual C# et Microsoft Visual Basic .NET fournissent des constructions de gestion des exceptions structurées. C# fournit la construction try / catch et finally. Protégez le code en le plaçant dans des blocs try et implémentez des blocs catch pour consigner et traiter les exceptions. Utilisez également la construction finally pour vous assurer que les ressources système critiques telles que les connexions sont fermées, qu'une condition d'exception se produise ou non.

try
{
   // Code susceptible de générer une exception
}
catch(Exception ex)
{
   // Code en charge de gérer l'exception et de consigner les détails dans un journal
   // pour faciliter le diagnostic des problèmes
}
finally
{
   // Ce code est toujours exécuté, qu'il y ait eu
   // une exception ou non. Placez le code de nettoyage dans des blocs
   // finally pour vous assurer que les ressources sont fermées et/ou libérées.
}

Utilisez une gestion des exceptions structurée plutôt que de renvoyer des codes d'erreur de méthodes, car il est facile d'oublier de vérifier un code renvoyé et ainsi de se retrouver dans un mode non sécurisé.

Ne pas enregistrer des données sensibles

Les nombreux détails d'exception inclus dans les objets Exception sont précieux pour les développeurs, mais aussi pour les pirates. Enregistrez les détails sur le serveur en les écrivant dans le journal d'événements pour faciliter le diagnostique des problèmes. Évitez d'enregistrer des données sensibles ou privées telles que des mots de passe utilisateur. Vérifiez également que les détails d'exceptions ne peuvent pas se propager au-delà de la limite de l'application vers le client comme décrit dans la rubrique suivante.

Ne pas révéler les informations sensibles sur le système ou l'application

Ne révélez pas trop d'informations à l'appelant. Les détails d'exceptions peuvent inclure les numéros de version du système d'exploitation et de .NET Framework, les noms de méthodes, les noms d'ordinateurs, les instructions de commandes SQL, les chaînes de connexion et d'autres détails qui sont très utiles aux pirates. Enregistrez les messages d'erreur détaillés sur le serveur et renvoyez les messages d'erreur génériques à l'utilisateur final.

Dans le contexte d'une application Web ASP.NET ou d'un service Web, vous pouvez le faire en configurant l'élément <customErrors> de manière appropriée. Pour plus d'informations, consultez le module 10 « Création de pages Web et de contrôles ASP.NET sécurisés ».

Prendre en compte les problèmes de filtre d'exceptions

Si votre code utilise des filtres d'exceptions, il est potentiellement vulnérable aux problèmes de sécurité car le code d'un filtre situé en haut de la pile d'appels peut être exécuté avant le code d'un bloc finally. Vérifiez que votre code ne repose pas sur les changements d'état dans le bloc finally parce que le changement d'état ne se produira qu'après l'exécution du filtre d'exceptions. Prenez par exemple le code suivant :

// Placer ce code dans un projet de bibliothèque de classe C#
public class SomeClass
{
  public void SomeMethod()
  {
    try
    {
      // (1) Générer une exception
      Console.WriteLine("1> Sur le point de rencontrer une condition d'exception");
      // Simuler une exception
      throw new Exception("Exception quelconque");
    }
    // (3) Le bloc finally
    finally
    {
      Console.WriteLine("3> Finally");
    }
  }
}

// Placer ce code dans un projet d'application de console Visual Basic.NET et
// faire référence au code de bibliothèque de classe ci-dessus
Sub Main()
    Dim c As New SomeClass
    Try
        c.SomeMethod()
    Catch ex As Exception When Filter()
        ' (4) L'exception est gérée
        Console.WriteLine("4> Principal : intercepter ex en tant qu'exception")
    End Try
End Sub

' (2) Le filtre d'exception
Public Function Filter() As Boolean
    ' Du code malintentionné peut agir ici si vous comptez sur un changement d'état 
    ' dans le bloc Finally de SomeClass pour assurer la sécurité
    Console.WriteLine("2> Filter")
    Return True ' Indique que l'exception est gérée
End Function

Dans l'exemple ci-dessus, Visual Basic .NET est utilisé pour appeler le code de bibliothèque de classes C# car, contrairement à C#, Visual Basic .NET prend en charge les filtres d'exceptions.

Si vous créez deux projets et qu'ensuite vous exécutez le code, le résultat obtenu apparaît ci-dessous :

1> Sur le point de rencontrer une condition d'exception
2> Filtre
3> Finally
4> Principal : intercepter ex en tant qu'exception

À partir de ce résultat, vous pouvez voir que le filtre d'exceptions s'exécute avant le code du bloc finally. Si votre code configure un état qui a un impact sur une décision de sécurité dans le bloc finally, un code malveillant appelant votre code peut ajouter un filtre d'exceptions pour exploiter cette vulnérabilité.

Prendre en compte un cadre de gestion des exceptions

Un système de gestion des exceptions formalisé peut permettre d'améliorer la capacité de prise en charge et la facilité de maintenance du système et de garantir une détection, un enregistrement et un traitement cohérents des exceptions.

Pour plus d'informations sur la manière de créer un cadre de gestion des exceptions et sur les meilleurs pratiques de gestion des exceptions pour les applications .NET, consultez le guide « Exception Management Architecture Guide » de MSDN Library à l'adresse http://msdn.microsoft.com/library/en-us/dnbda/html/exceptdotnet.asp.

E/S sur fichier

Les problèmes de canonicalisation représentent un point important pour tout code qui accède au système de fichiers. Si vous avez le choix, ne basez pas les décisions de sécurité sur les noms de fichiers d'entrée car un seul nom de fichier peut être représenté de nombreuses manières. Si votre code doit accéder à un fichier à l'aide d'un nom de fichier fourni par l'utilisateur, prenez les mesures nécessaires pour que votre assembly ne puisse pas être utilisé par un utilisateur malveillant qui souhaiterait accéder à des données sensibles ou les remplacer.

Les recommandations suivantes permettent d'améliorer la sécurité de vos E/S sur fichier :

  • éviter les entrées de noms de fichiers non approuvées ;

  • ne pas faire confiance aux variables d'environnement ;

  • valider les noms de fichiers d'entrée ;

  • limiter les E/S sur fichier au contexte de votre application.

Éviter les entrées de noms de fichiers non approuvées

Évitez d'écrire du code acceptant qu'un appelant entre un nom de fichier ou de chemin d'accès et utilisez plutôt des noms de fichiers et des emplacements fixes lorsque vous lisez et écrivez des données. Ainsi votre code ne pourra pas être contraint d'accéder à des fichiers arbitraires.

Ne pas faire confiance aux variables d'environnement

Essayez d'utiliser des chemins d'accès aux fichiers absolus lorsque vous le pouvez. Ne faites pas confiance aux variables d'environnement pour construire des chemins d'accès aux fichiers car vous ne pouvez pas garantir la valeur de la variable d'environnement.

Valider les noms de fichiers d'entrée

Si vous n'avez pas besoin que l'appelant vous envoie des noms de fichiers d'entrée, assurez-vous que le nom de fichier est strictement correct pour déterminer s'il est valide ou non. Il y a deux aspects de la validation des chemins d'accès aux fichiers d'entrée. Vous devez :

  • vérifier les noms de système de fichiers valides ;

  • vérifier la validité de l'emplacement, telle qu'elle est définie par le contexte de votre application. Par exemple, se trouvent-ils dans la hiérarchie de répertoires de votre application ?

Pour valider le chemin d'accès et le nom du fichier, utilisez la méthode System.IO.Path.GetFullPath comme indiqué dans l'échantillon de code suivant. Cette méthode canonicalise aussi le nom de fichier fourni.

using System.IO;

public static string ReadFile(string filename)
{
  // Obtenir un nom de fichier canonicalisé et valide
  string name = Path.GetFullPath(filename);
  // Maintenant, ouvrir le fichier
}

Dans le cadre du processus de canonicalisation, GetFullPath procède aux vérifications suivantes :

  • il vérifie que le nom de fichier ne contient pas de caractères non valides, comme défini par Path.InvalidPathChars ;

  • il vérifie que le nom de fichier se rapporte à un fichier et non à un autre type de périphérique tel qu'une unité physique, un canal nommé, un tiroir de chargement ou un périphérique DOS tel que LPT1, COM1, AUX ou d'autres périphériques ;

  • il vérifie que le chemin d'accès et le nom de fichier combinés ne sont pas trop longs ;

  • il supprime les caractères redondants tels que les points de fin ;

  • il rejette les noms de fichiers qui utilisent le format //?/.

Limiter les E/S sur fichier au contexte de votre application

Une fois que vous savez que le nom de fichier du système de fichiers est correct, vous devez souvent vérifier s'il est valide dans le contexte de votre application. Par exemple, vous devrez probablement vérifier qu'il se trouve dans la hiérarchie de répertoires de votre application et que votre code ne peut pas accéder aux fichiers arbitraires du système de fichiers. Pour plus d'informations sur la manière d'utiliser la sécurité d'accès au code pour limiter les E/S sur fichier, consultez la section « E/S de fichier » du module 8 « La sécurité d'accès au code en pratique ».

Journal d'événements

Lorsque vous écrivez un code de journalisation d'événements, tenez compte des menaces de falsification et de divulgation des informations. Par exemple, un pirate peut-il collecter des données sensibles en accédant aux journaux d'événements ? Un pirate peut-il effacer des suivis en supprimant les journaux et en effaçant des enregistrements particuliers ?

L'accès direct aux journaux d'événements à l'aide d'outils d'administration du système tels que l'Observateur d'événements est restreint par la sécurité Windows. Votre principale préoccupation devrait être de vous assurer que le code de journalisation des événements que vous écrivez ne peut pas être utilisé par un utilisateur malveillant pour accéder sans autorisation au journal d'événements.

Pour éviter la divulgation de données sensibles, ne les enregistrez pas n'importe où. Par exemple, n'enregistrez pas d'informations d'authentification de compte. De même, votre code ne pourra pas être exploité pour lire des enregistrements existants ou pour supprimer des journaux d'événements s'il se limite à écrire de nouveaux enregistrements à l'aide de EventLog.WriteEvent. La principale menace à traiter dans cet exemple consiste à éviter qu'un appelant malveillant appelle votre code près d'un million de fois de manière à forcer un cycle de fichier journal à écraser les entrées précédentes du journal afin d'effacer les pistes. Le meilleur moyen de résoudre ce problème est d'utiliser un mécanisme hors bande, en utilisant par exemple l'instrumentation Windows pour alerter les opérateurs dès que le journal d'événements approche de son seuil.

Enfin, vous pouvez utiliser la sécurité d'accès au code et l'autorisation EventLogPermission pour définir spécifiquement ce que votre code est autorisé à faire lorsqu'il accède au journal d'événements. Par exemple, si vous écrivez un code devant uniquement lire des enregistrements du journal d'événements, vous devez le limiter avec une autorisation EventLogPermission qui prend uniquement en charge l'accès en navigation. Pour plus d'informations sur la manière de limiter le code de journalisation des événements, consultez la section « Journal d'événements » du module 8 « La sécurité d'accès au code en pratique ».

Registre

Le Registre peut fournir un emplacement sécurisé pour stocker les données sensibles de configuration de l'application, telles que les chaînes de connexion à la base de données cryptées. Vous pouvez stocker les données de configuration sous la clé de l'ordinateur local unique (HKEY_LOCAL_MACHINE) ou sous la clé de l'utilisateur actuel (HKEY_CURRENT_USER). Dans tous les cas, cryptez les données à l'aide de DPAPI et stockez les données cryptées et non le texte clair.

HKEY_LOCAL_MACHINE

Si vous stockez les données de configuration sous HKEY_LOCAL_MACHINE, rappelez-vous que n'importe quel processus de l'ordinateur local peut potentiellement accéder aux données. Pour restreindre l'accès, appliquez une liste de contrôle d'accès (ACL) restrictive à la clé de Registre spécifique pour limiter l'accès aux administrateurs et à votre jeton de processus ou de thread spécifique. Lorsque vous utilisez HKEY_LOCAL_MACHINE, il est plus facile de stocker les données de configuration au moment de l'installation, mais aussi d'en assurer la maintenance ultérieurement.

HKEY_CURRENT_USER

Si vos exigences de sécurité vous dictent une solution de stockage encore moins accessible, utilisez une clé sous HKEY_CURRENT_USER. Cette approche implique que vous n'avez pas à configurer explicitement les ACL parce que l'accès à la clé de l'utilisateur actuel est automatiquement restreint en fonction de l'identité du processus.

HKEY_CURRENT_USER restreint encore davantage l'accès parce qu'un processus peut uniquement accéder à la clé de l'utilisateur actuel si le profil utilisateur associé au jeton de thread ou de processus actuel est chargé.

Sur Windows 2000, la version 1.1 de .NET Framework charge le profil utilisateur du compte ASPNET. Sur Windows Server 2003, le profil de ce compte est uniquement chargé si le modèle de processus ASP.NET est utilisé. Il n'est pas chargé explicitement par Internet Information Services (IIS) 6 si le modèle de processus IIS 6 est utilisé sur Windows Server 2003.

Remarque : la version 1.0 de .NET Framework ne charge pas le profil utilisateur ASPNET, ce qui rend l'option HKEY_CURRENT_USER moins pratique.

Lecture à partir du Registre

Le fragment de code suivant montre comment lire une chaîne de connexion à la base de données cryptée à partir de la clé HKEY_CURRENT_USER en utilisant la classe Microsoft.Win32.Registry.

using Microsoft.Win32;
public static string GetEncryptedConnectionString()
{
  return (string)Registry.
                 CurrentUser.
                 OpenSubKey(@"LOGICIEL\VotreApp").
                 GetValue("connectionString");
}

Pour plus d'informations sur la manière d'utiliser l'autorisation de stratégie d'accès au code RegistryPermission pour limiter le code d'accès au Registre, en le restreignant par exemple à des clés spécifiques, consultez la section « Registre » du module 8 « La sécurité d'accès au code en pratique ».

Accès aux données

Deux des plus importants facteurs à prendre en compte lorsque votre code accède à une base de données sont la gestion sécurisée des chaînes de connexion à la base de données et la construction des instructions SQL ainsi que la validation de la saisie pour éviter les attaques par injection SQL. De même, lorsque vous écrivez un code d'accès aux données, tenez compte des exigences d'autorisation du fournisseur de données ADO.NET que vous avez choisi. Pour des informations détaillées sur ces problèmes d'accès aux données et autres, consultez le module 14 « Création d'un accès sécurisé aux données ».

Pour plus d'informations sur la manière d'utiliser SqlClientPermission pour limiter l'accès aux données de SQL Server à l'aide du fournisseur de données SQL Server d'ADO.NET, consultez la section « Accès aux données » du module 8 « La sécurité d'accès au code en pratique ».

Code non géré

Le code géré, .NET Framework et l'exécution du langage commun éliminent plusieurs vulnérabilités liées à la sécurité souvent présentes dans le code non géré. La vérification de type sécurisé du code est un bon exemple de l'aide apportée par .NET Framework. Il rend le dépassement de la capacité de la mémoire tampon pratiquement impossible dans un code géré, ce qui ne permet pas d'éliminer la menace d'une injection de code basée sur la pile.

Cependant, si vous disposez de composants COM existants ou de DLL Win32 que vous devez réutiliser, utilisez les couches d'interopérabilité P/Invoke (Platform Invocation Services) ou COM pour les lier à votre assembly.

Lorsque vous appelez un code non géré, il est vital que votre code géré valide chaque paramètre d'entrée passé à l'API non gérée pour se prémunir contre le dépassement potentiel de la capacité de la mémoire tampon. De même, soyez prudent lorsque vous manipulez les paramètres de sortie issus de l'API non gérée.

Vous devez isoler les appels vers un code non géré dans un assembly de wrappers séparé. Vous pouvez ainsi mettre en sandbox le code hautement privilégié et isoler les exigences d'autorisation de la sécurité d'accès au code dans un assembly spécifique. Pour plus de détails sur la mise en sandbox et pour des instructions supplémentaires sur la sécurité d'accès au code que vous devez appliquer lors de l'appel d'un code non géré, consultez la section « Code non géré » du module 8 « La sécurité d'accès au code en pratique ». Les recommandations suivantes permettent d'améliorer la sécurité de vos appels d'API non gérées, sans utiliser de techniques explicites de codage de la sécurité d'accès au code :

  • valider les paramètres de chaîne d'entrée et de sortie ;

  • valider les tailles de tableau ;

  • vérifier les longueurs des chemins d'accès aux fichiers ;

  • compiler le code non géré avec le commutateur /GS ;

  • inspecter le code non géré à la recherche d'API « dangereuses ».

Validation des paramètres de chaîne d'entrée et de sortie

Les paramètres de chaîne passés aux API non gérées sont la source principale du dépassement de la capacité de la mémoire tampon. Vérifiez la longueur de toutes les chaînes d'entrée de votre code wrapper pour vous assurer qu'elle ne dépasse pas la limite définie par l'API non gérée. Si l'API non gérée accepte un pointeur de caractère, il se peut que vous ne connaissiez pas la longueur de chaîne maximum autorisée, à moins que vous n'ayez accès à la source non gérée. L'exemple suivant est une vulnérabilité courante.

void SomeFunction( char *pszInput )
{
  char szBuffer[10];
  // Observation ; pas de contrôle de longueur. L'entrée est copiée directement dans le tampon
  // Contrôle de la longueur ou emploi de strncpy
  strcpy(szBuffer, pszInput);
  . . .
}

Si vous ne pouvez pas examiner le code non géré parce qu'il ne vous appartient pas, testez rigoureusement l'API en passant des chaînes d'entrée délibérément longues.

Si votre code utilise un StringBuilder pour recevoir une chaîne passée par une API non gérée, vérifiez qu'il peut conserver la chaîne la plus longue pouvant être soumise par l'API non gérée.

Validation des tailles de tableau

Si vous passez une entrée dans une API non gérée en utilisant un tableau, assurez-vous que le wrapper géré vérifie que la capacité du tableau n'est pas dépassée.

Vérification des longueurs des chemins d'accès aux fichiers

Si l'API non gérée accepte un nom de fichier et un chemin d'accès, vérifiez qu'ils ne dépassent pas 260 caractères. Cette limite est définie par la constante MAX_PATH de Win32. Il est très courant qu'un code non géré alloue une mémoire tampon de cette longueur pour manipuler des chemins d'accès aux fichiers.

Remarque : la longueur maximum des noms de répertoire et des clés de Registre est de 248 caractères.

Compilation du code non géré avec le commutateur /GS

Si vous possédez le code non géré, compilez-le en utilisant le commutateur /GS pour activer des sondes de pile afin de détecter le dépassement de la capacité de la mémoire tampon. Pour plus d'informations sur le commutateur /GS, consultez l'article 325483 « WebCast: Compiler Security Checks: The /GS compiler switch » de la Base de connaissances de Microsoft à l'adresse : http://support.microsoft.com/kb/325483.

Inspection du code non géré pour rechercher les API dangereuses

Si vous avez accès au code source du code non géré que vous appelez, vous devez le soumettre à un examen minutieux, en prêtant particulièrement attention à la gestion des paramètres pour vous assurer qu'aucun dépassement de la capacité de la mémoire tampon n'est possible et qu'il n'utilise pas d'API potentiellement dangereuses. Pour plus d'informations, consultez le module 21 « Examen du code ».

Délégués

Les délégués sont l'équivalent géré des pointeurs fonction de type sécurisé et sont utilisés par .NET Framework pour prendre en charge les événements. L'objet Delegate maintient une référence à une méthode, qui est appelée lorsque le délégué est invoqué. Les événements permettent d'enregistrer plusieurs méthodes comme gestionnaires d'événements. Lorsqu'un événement se produit, tous les gestionnaires d'événements sont appelés.

Refus de délégués de sources non approuvées

Si votre assembly expose un délégué ou un événement, sachez que n'importe quel code peut associer une méthode au délégué et que vous ne savez pas par avance ce que le code va faire. La stratégie la plus sûre consiste à refuser les délégués d'appelants non approuvés. Si votre assembly intègre un nom fort et ne comprend pas l'attribut AllowPartiallyTrustedCallersAttribute, seuls les appelants de confiance totale peuvent vous passer un délégué.

Si votre assembly prend en charge des appelants de confiance partielle, n'oubliez pas qu'il existe une menace qu'un délégué soit passé par un code malveillant. Pour connaître les techniques d'atténuation des risques permettant de faire face à cette menace, consultez la section « Délégués » du module 8 « La sécurité d'accès au code en pratique ».

Sérialisation

Il se peut que vous deviez ajouter une prise en charge de la sérialisation dans une classe pour pouvoir la trier par valeur à travers une limite distante .NET (c'est-à-dire, à travers les domaines d'application, les processus ou les ordinateurs) ou pour pouvoir rendre l'état d'un objet persistant afin de créer un flux de données uniforme, à des fins de stockage sur le système de fichiers, par exemple.

Par défaut, les classes ne peuvent pas être sérialisées. Une classe peut être sérialisée si elle est marquée par l'attribut SerializableAttribute ou si elle est dérivée de ISerializable. Si vous utilisez la sérialisation, respectez les consignes suivantes :

  • ne pas sérialiser des données sensibles ;

  • valider les flux de données sérialisés.

Ne pas sérialiser des données sensibles

Idéalement, si votre classe contient des données sensibles, ne prenez pas en charge la sérialisation. Si vous avez besoin de sérialiser votre classe et qu'elle contient des données sensibles, évitez de sérialiser les champs qui contiennent les données sensibles. Pour ce faire, implémentez ISerializable pour contrôler le comportement de la sérialisation ou insérez l'attribut [NonSerialized] dans les champs qui contiennent des données sensibles. Par défaut, tous les champs publics et privés sont sérialisés.

L'exemple suivant montre comment utiliser l'attribut [NonSerialized] pour garantir qu'un champ spécifique contenant des données sensibles ne pourra pas être sérialisé.

[Serializable]
public class Employee {
  // D'accord pour que le nom soit sérialisé
  private string name;
  // Empêcher le salaire d'être sérialisé
  [NonSerialized] private double annualSalary;
  . . .
}

Sinon, implémentez l'interface ISerializable et contrôlez explicitement le processus de sérialisation. Si vous devez sérialiser l'élément ou les éléments de données sensibles, pensez à crypter d'abord les données. Le code qui désérialise votre objet doit avoir accès à la clé de décryptage.

Valider les flux de données sérialisés

Lorsque vous créez une instance d'objet à partir d'un flux de données sérialisé, ne supposez pas que le flux contient des données valides. Pour éviter que des données potentiellement dangereuses soient injectées dans l'objet, validez chaque champ au moment où il est reconstitué comme indiqué dans l'échantillon de code suivant.

public void DeserializationMethod(SerializationInfo info, StreamingContext cntx)
{
  string someData = info.GetString("nomQuelconque");
  // Techniques de validation de saisie pour valider ces données.
}

Pour plus d'informations sur les techniques de validation de la saisie, consultez la section « Validation de la saisie » du module 10 « Création de pages Web et de contrôles ASP.NET sécurisés ».

Éléments à prendre en compte pour la confiance partielle

Si votre code prend en charge des appelants de confiance partielle, vous devez faire face à des menaces supplémentaires. Par exemple, un code malveillant peut passer un flux de données sérialisé ou peut tenter de sérialiser les données sur votre objet. Pour connaître les techniques d'atténuation des risques permettant de faire face à ces menaces, consultez la section « Sérialisation » du module 8 « La sécurité d'accès au code en pratique ».

Thread

Les bogues causés par les conflits d'accès du code multithread peuvent entraîner des vulnérabilités de la sécurité et un code généralement instable sujet aux bogues liés à la durée. Si vous développez des assemblys multithread, tenez compte des recommandations suivantes :

  • ne pas mettre en cache les résultats des contrôles de la sécurité ;

  • tenir compte des jetons d'emprunt d'identité ;

  • synchroniser les constructeurs de classe statique ;

  • synchroniser les méthodes Dispose.

Ne pas mettre en cache les résultats des contrôles de la sécurité

Si votre code multithread met en cache les résultats d'un contrôle de la sécurité, peut-être dans une variable statique, le code est potentiellement vulnérable comme on peut le voir dans l'échantillon de code suivant.

   public void AccessSecureResource()
   {
     _callerOK = PerformSecurityDemand();
     OpenAndWorkWithResource();
     _callerOK = false;
   }
   private void OpenAndWorkWithResource()
   {
     if (_callerOK)
       PerformTrustedOperation();
     else
     {
       PerformSecurityDemand();
       PerformTrustedOperation();
     }
   }

S'il existe d'autres chemins d'accès à OpenAndWorkWithResource, et qu'un autre thread appelle la méthode sur le même objet, il est possible que le second thread omette la demande de sécurité, car il voit la commande _callerOK=true, configurée par un autre thread.

Tenir compte des jetons d'emprunt d'identité

Lorsque vous créez un nouveau thread, il endosse le contexte de sécurité défini par le jeton au niveau du processus. Si un thread parent emprunte une identité pendant qu'il crée un nouveau thread, le jeton d'emprunt d'identité n'est pas passé au nouveau thread.

Synchroniser les constructeurs de classe statique

Si vous utilisez des constructeurs de classe statique, assurez-vous qu'ils ne sont pas vulnérables aux conflits d'accès. Si, par exemple ils manipulent l'état statique, ajoutez une synchronisation de thread pour éviter les vulnérabilités potentielles.

Synchroniser les méthodes Dispose

Si vous développez des implémentations Dispose non synchronisées, le code Dispose peut être appelé plusieurs fois sur des threads séparés. L'échantillon de code suivant en montre un exemple.

void Dispose()
{
  if (null != _theObject)
  {
    ReleaseResources(_theObject);
    _theObject = null;
  }
}

Dans cet exemple, il est possible pour deux threads d'exécuter le code avant que le premier thread ait configuré la référence _theObject sur null. Selon les fonctionnalités fournies par la méthode ReleaseResources, des vulnérabilités de la sécurité peuvent se produire.

Réflexion

Avec la réflexion, vous pouvez charger dynamiquement des assemblys, découvrir des informations sur les types et exécuter du code. Vous pouvez également obtenir une référence à un objet et acquérir ou configurer ses membres privés. Les nombreuses implications pour la sécurité sont les suivantes :

  • Si votre code utilise la réflexion pour se refléter sur d'autres types, assurez-vous que seul un code approuvé peut vous appeler. Utilisez les demandes d'autorisation de sécurité d'accès au code pour autoriser un code appelant. Pour plus d'informations, consultez le module 8 « La sécurité d'accès au code en pratique ».

  • Si vous chargez dynamiquement des assemblys, en utilisant par exemple System.Reflection.Assembly.Load, n'utilisez pas de noms d'assemblys ou de types qui vous ont été passés par des sources non approuvées.

  • Si vos assemblys génèrent dynamiquement du code pour effectuer des opérations pour un appelant, assurez-vous que l'appelant ne peut en aucun cas influencer le code généré. Ce problème a plus d'envergure si le niveau de confiance de l'appelant est inférieur à celui de l'assembly qui génère le code.

  • Si la génération de votre code repose sur les entrées de l'appelant, soyez particulièrement vigilant vis-à-vis des vulnérabilités de la sécurité. Validez toute chaîne de saisie utilisée comme littéral de chaîne dans le code généré et effacez les guillemets pour être certain que l'appelant ne pourra pas briser le littéral et injecter du code. En général, s'il existe un moyen pour l'appelant d'influencer la génération de code afin de faire échouer la compilation, c'est qu'il existe probablement une vulnérabilité de la sécurité.

Pour plus d'informations, consultez l'article « Secure Coding Guidelines for the .NET Framework » dans MSDN Library.

Obscurcissement

Si vous souhaitez protéger la propriété intellectuelle, vous pouvez rendre extrêmement difficile l'utilisation d'un décompilateur sur le code MSIL de vos assemblys, en utilisant un outil d'obscurcissement. Un outil d'obscurcissement brouille l'interprétation humaine des instructions MSIL et permet d'empêcher la réussite d'une décompilation.

L'obscurcissement n'est pas infaillible et il n'est pas conseillé de générer des solutions de sécurité qui reposent dessus. En revanche, l'obscurcissement peut contrecarrer les menaces en raison de sa capacité à soumettre le code à un processus d'ingénierie inverse. Les outils d'obscurcissements fournissent généralement les avantages suivants :

  • ils permettent de protéger votre propriété intellectuelle ;

  • ils obscurcissent les chemins d'accès, ce qui fait qu'il est plus difficile pour un pirate de pirater une logique de sécurité ;.

  • ils décomposent les noms des variables membres internes, ce qui rend le code plus difficile à comprendre ;

  • ils cryptent les chaînes. Les pirates essayent souvent de rechercher des chaînes spécifiques pour localiser une logique clé sensible. Le cryptage de chaîne rend cette tâche bien plus compliquée.

Il existe plusieurs outils d'obscurcissement pour .NET Framework. L'un d'entre eux, l'outil Community Edition of the Dotfuscator de PreEmptive Solutions, est inclus avec le système de développement Microsoft Visual Studio® .NET 2003. Il est également disponible sur Internet à l'adresse http://www.preemptive.com/dotfuscator. Pour plus d'informations, consultez la liste des outils d'obscurcissement à l'adresse http://www.gotdotnet.com/team/csharp/tools/default.aspx.

Cryptographie

La cryptographie est l'un des outils les plus importants pouvant être utilisé pour protéger les données. Le cryptage permet d'assurer la confidentialité des données et de fournir des algorithmes de hachage, qui produisent une représentation fixe et condensée des données, et peut être utilisé pour protéger les données de la falsification. Les signatures numériques peuvent également être utilisées à des fins d'authentification.

Il est conseillé d'utiliser le cryptage lorsque vous souhaitez sécuriser les données en transit ou en stockage. Certains algorithmes de cryptage fonctionnent mieux que d'autres car ils assurent un cryptage renforcé. Généralement, plus les tailles de clé de cryptage sont larges, plus la sécurité est renforcée.

Deux des erreurs les plus courantes relevées lors de l'utilisation de la cryptographie sont le développement de vos propres algorithmes de cryptage et l'incapacité de sécuriser vos clés de cryptage. Les clés de cryptage doivent être gérées avec soin. Un pirate doté de votre clé de cryptage peut accéder à vos données cryptées.

Les principaux problèmes rencontrés sont les suivants :

  • utilisation des services cryptographiques fournis par la plate-forme ;

  • génération de clés ;

  • stockage de clés ;

  • échange de clés ;

  • maintenance de clés.

Utilisation des services cryptographiques fournis par la plate-forme

Ne créez pas vos propres implémentations cryptographiques. Il est très peu probable que ces implémentations seront aussi sécurisées que les algorithmes standard de l'industrie fournis par la plate-forme, c'est-à-dire, le système d'exploitation et .NET Framework. Un code géré doit utiliser les algorithmes fournis par l'espace de noms System.Security.Cryptography pour le cryptage, le décryptage, le hachage, la génération de numéros aléatoires et les signatures numériques.

Beaucoup des types de cet espace de noms composent l'outil CryptoAPI du système d'exploitation, tandis que d'autres implémentent des algorithmes dans le code géré.

Génération de clés

Les recommandations ci-dessous doivent être appliquées lors de la création de clés de cryptage :

  • générer des clés aléatoires ;

  • utiliser PasswordDeriveBytes pour le cryptage basé sur un mot de passe ;

  • utiliser de préférence des clés étendues.

Génération de clés aléatoires

Si vous devez générer des clés de cryptage par programmation, utilisez RNGCryptoServiceProvider pour créer des clés et des vecteurs d'initialisation et n'utilisez pas la classe Random. Contrairement à la classe Random, RNGCryptoServiceProvider crée des numéros aléatoires cryptographiquement sûrs et conformes à la norme FIPS-140. Le code suivant montre comment utiliser cette fonction.

using System.Security.Cryptography;
. . .
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] key = new byte[keySize];
rng.GetBytes(key);
Utilisation de PasswordDeriveBytes pour le cryptage basé sur un mot de passe

L'espace de noms System.Security.Cryptography.DeriveBytes fournit PasswordDeriveBytes qui peut être utilisé pour le cryptage des données basé sur un mot de passe fourni par l'utilisateur. Pour décrypter, l'utilisateur doit fournir le même mot de passe que celui qui a servi à crypter.

Remarque : cette approche ne convient pas à l'authentification par mot de passe. Stockez un vérificateur de mot de passe sous forme de valeur de hachage avec un salt (nombre aléatoire) de manière à authentifier un mot de passe utilisateur. Utilisez PasswordDeriveBytes pour générer des clés pour le cryptage basé sur un mot de passe.

PasswordDeriveBytes accepte un mot de passe, un salt, un algorithme de cryptage, un algorithme de hachage, une taille de clé (en bits) et des vecteurs d'initialisation pour créer une clé symétrique destinée au cryptage.

Après avoir utilisé la clé pour crypter les données, effacez-la de la mémoire mais conservez le salt et le vecteur d'initialisation. Ces valeurs doivent être protégées et sont nécessaires pour régénérer la clé lors du décryptage.

Pour plus d'informations sur le stockage des hachages de mot de passe avec salt, consultez le module 14 « Création d'un accès sécurisé aux données ».

Utilisation préférentielle de clés étendues

Lors de la génération d'une clé ou d'une paire de clés de cryptage, utilisez la taille de clé la plus large possible pour l'algorithme. Ceci ne sécurise pas nécessairement davantage l'algorithme, mais augmente considérablement le temps nécessaire pour réussir une attaque en force de la clé. Le code suivant vous montre comment trouver la taille de clé la plus large prise en charge pour un algorithme particulier.

private int GetLargestSymKeySize(SymmetricAlgorithm symAlg)
{
  KeySizes[] sizes = symAlg.LegalKeySizes;
  return sizes[sizes.Length].MaxSize;
}

private int GetLargestAsymKeySize(AsymmetricAlgorithm asymAlg)
{
  KeySizes[] sizes = asymAlg.LegalKeySizes;
  return sizes[sizes.Length].MaxSize;
}

Stockage de clés

Lorsque cela est possible, utilisez une solution de cryptage fournie par la plate-forme qui vous permet d'éviter la gestion des clés dans votre application. Cependant, vous aurez parfois besoin d'utiliser des solutions de cryptage qui exigent que vous stockiez les clés. L'utilisation d'un emplacement de stockage des clés sécurisé est indispensable. Utilisez les techniques suivantes pour éviter les vulnérabilités liées au stockage des clés :

  • utiliser DPAPI pour éviter la gestion des clés ;

  • ne pas stocker les clés dans le code ;

  • restreindre l'accès aux clés persistantes.

Utilisation de DPAPI pour éviter la gestion des clés

DPAPI est une fonctionnalité de cryptage/décryptage native fournie par Microsoft Windows 2000. L'un des principaux avantages fournis par l'utilisation de DPAPI est que la clé de cryptage est gérée par le système d'exploitation, parce que la clé est dérivée du mot de passe associé au compte du processus (ou au compte de thread si le thread emprunte une identité) qui appelle les fonctions DPAPI.

Clé utilisateur contre clé de l'ordinateur

Vous pouvez effectuer un cryptage avec DPAPI en utilisant soit la clé utilisateur, soit la clé de l'ordinateur. Par défaut, DPAPI utilise une clé utilisateur. Cela signifie que seul un thread exécutant le contexte de sécurité du compte utilisateur qui a crypté les données peut les décrypter. Vous pouvez demander à DPAPI d'utiliser la clé de l'ordinateur en passant l'indicateur CRYPTPROTECT_LOCAL_MACHINE dans l'API CryptProtectData. Dans ce cas, tout utilisateur de l'ordinateur actuel peut décrypter les données.

L'option de la clé utilisateur peut être utilisée uniquement si le compte utilisé pour effectuer le cryptage a chargé un profil utilisateur. Si vous exécutez le code dans un environnement n'ayant pas chargé un profil utilisateur, vous ne pourrez pas utiliser facilement le magasin d'utilisateurs et devrez opter à la place pour le magasin de l'ordinateur.

Sur Windows 2000, la version 1.1 de .NET Framework charge le profil utilisateur du compte ASPNET utilisé pour exécuter les applications Web. La version 1.0 de .NET Framework ne charge pas le profil de ce compte, ce qui rend plus difficile l'utilisation de DPAPI avec la clé utilisateur.

Si vous utilisez l'option de la clé de l'ordinateur, vous devez utiliser une ACL pour sécuriser les données cryptées, par exemple dans une clé de Registre, et utiliser cette approche pour limiter les utilisateurs ayant accès aux données cryptées. Pour plus de sécurité, passez également une valeur d'entropie facultative dans les fonctions de DPAPI.

Remarque : une valeur d'entropie est une valeur aléatoire supplémentaire pouvant être passée dans les fonctions CryptProtectData et CryptUnprotectData de DPAPI. La valeur utilisée pour crypter les données doit également être utilisée pour les décrypter. L'option de la clé de l'ordinateur implique que tout utilisateur de l'ordinateur peut décrypter les données. En ajoutant une entropie, l'utilisateur doit également connaître la valeur d'entropie.

L'inconvénient de l'utilisation de l'entropie est que vous devez gérer la valeur d'entropie comme vous gèreriez une clé. Pour éviter les problèmes de gestion de l'entropie, utilisez le magasin de l'ordinateur sans entropie et validez minutieusement les utilisateurs et le code (en utilisant la sécurité d'accès au code) avant d'appeler le code DPAPI.

Pour plus d'informations sur l'utilisation de DPAPI à partir des applications Web ASP.NET, consultez l'article « How To: Create a DPAPI Library » de la section How To de « Building Secure ASP.NET Applications » à l'adresse http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT07.asp.

Ne pas stocker les clés dans le code

Ne stockez pas les clés dans le code car les clés pré-programmées de votre assembly compilé peuvent être décomposées à l'aide d'outils similaires à ILDASM, qui afficheront votre clé en texte plein.

Restriction de l'accès aux clés persistantes

Lorsque vous stockez des clés avec stockage persistant pour les utiliser au moment de l'exécution, utilisez des ACL appropriées et limitez l'accès à la clé. L'accès à la clé doit être accordé uniquement aux administrateurs, au SYSTEM et à l'identité du code au moment de l'exécution, par exemple le compte ASPNET ou de service réseau.

Lorsque vous sauvegardez une clé, ne la stockez pas en texte plein, cryptez-la à l'aide de DPAPI ou d'un mot de passe sûr et placez-la sur un support amovible.

Échange de clés

Certaines applications exigent l'échange sécurisé de clés de cryptage sur un réseau non sécurisé. Il se peut que vous deviez communiquer verbalement la clé ou l'envoyer via un courrier électronique sécurisé. Il existe une méthode plus sûre pour échanger une clé symétrique : le cryptage de clé publique. Avec cette approche, vous cryptez la clé symétrique à échanger en utilisant la clé publique de l'autre partie à partir d'un certificat pouvant être validé. Un certificat est considéré comme valide dans les cas suivants :

  • il est utilisé dans les intervalles de date spécifiés dans le certificat ;

  • toutes les signatures de la chaîne de certificat peuvent être vérifiées ;

  • son type est correct. Par exemple, un certificat de courrier électronique n'est pas utilisé comme un certificat de serveur Web ;

  • il peut être vérifié par une autorité racine de confiance ;

  • il ne se trouve pas sur une liste de révocation de certificat (CRL) de l'éditeur.

Maintenance des clés

La sécurité dépend de la capacité à préserver la sécurité de la clé durant une durée prolongée. Appliquez les recommandations suivantes pour la maintenance de clés :

  • renouveler les clés périodiquement ;

  • protéger les clés privées exportées.

Renouvellement périodique des clés

Il est conseillé de changer vos clés de cryptage de temps en temps parce qu'un secret statique est plus susceptible d'être découvert sur la durée. L'avez-vous écrit quelque part ? Bernard, l'administrateur des secrets, a-t-il changé de poste dans l'entreprise ou quitté l'entreprise ? Utilisez-vous la même clé de session pour crypter les communications depuis longtemps ? N'utilisez pas trop les clés.

Compromission de clés

Les clés peuvent être compromises de plusieurs manières. Par exemple, vous pouvez perdre une clé ou découvrir qu'un pirate a volé ou trouvé la clé.

Si la clé utilisée pour le cryptage asymétrique et l'échange de clés est compromise, ne continuez pas à l'utiliser, et informez les utilisateurs de la clé publique que la clé a été compromise. Si vous avez utilisé la clé pour signer des documents, vous devez les signer de nouveau.

Si la clé privée de votre certificat est compromise, contactez l'autorité de certification qui l'a émise pour que votre certificat soit placé sur une liste de révocation de certificats. Changez également la manière de stocker vos clés pour éviter des compromissions futures.

Protection des clés privées exportées

Utilisez PasswordDeriveBytes lorsque vous exportez une clé privée RSA (Rivest, Shamir, and Adleman) ou DSA (algorithme de signature numérique). Les classes RSA et DSA contiennent une méthode ToXmlString, qui vous permet d'exporter la clé publique ou privée, ou les deux, à partir du conteneur de clé. Cette méthode exporte la clé privée en texte plein. Si vous exportez la clé privée pour l'installer sur plusieurs serveurs d'un parc Web, il est recommandé d'utiliser une méthode de cryptage de la clé après avoir exporté la clé privée à l'aide de PasswordDeriveBytes pour générer une clé symétrique comme indiqué dans l'échantillon de code suivant.

PasswordDeriveBytes deriver = new PasswordDeriveBytes(<strong password>, null);
byte[] ivZeros = new byte[8];//Ce code n'est pas utilisé ici mais est
nécessaire.
//Tirer la clé du mot de passe
byte[] pbeKey = deriver.CryptDeriveKey("TripleDES", "SHA1", 192, ivZeros);

Résumé

Ce module vous a montré comment appliquer différentes techniques pour améliorer la sécurité de votre code géré. Les techniques de ce module peuvent être appliquées à tous les types d'assemblys gérés, notamment les pages Web, les contrôles, les bibliothèques d'utilitaires et autres. Pour obtenir des recommandations spécifiques qui s'appliquent à des types d'assemblys spécifiques, consultez les autres modules Création de la partie III de ce guide.

Pour améliorer encore la sécurité de vos assemblys, vous pouvez utiliser des techniques de codage de sécurité d'accès au code explicites, qui sont particulièrement importantes si vos assemblys prennent en charge des appelants de confiance partielle. Pour plus d'informations sur l'utilisation de la sécurité d'accès au code, consultez le module 8 « La sécurité d'accès au code en pratique ».

Ressources supplémentaires

Pour des informations complémentaires, consultez les ressources suivantes :

Cela vous a-t-il été utile ?
(1500 caractères restants)
© 2013 Microsoft. Tous droits réservés.