La sécurité d'accès au code en pratique
Sur cette page
Dans ce module
Objectifs
S'applique à
Explication de la sécurité d'accès au code
APTCA
Code privilégié
Demande d'autorisations
Autorisation du code
Demandes de liaison
Assert et RevertAssert
Restriction du code
E/S de fichier
Journal des événements
Registre
Accès aux données
Services d'annuaire
Variables d'environnement
Services Web
Sockets et DNS
Code non géré
Délégués
Sérialisation
Résumé
Ressources supplémentaires
Dans ce module
La sécurité d'accès au code est un modèle de contrainte de ressources conçu pour limiter les types de ressources système auxquels le code peut accéder, ainsi que les types d'opération privilégiée qu'il peut effectuer. Ces restrictions sont indépendantes de l'utilisateur qui appelle le code ou du compte utilisateur sous lequel le code est exécuté. Ce module commence par une description détaillée du mode de fonctionnement de la sécurité d'accès au code, suivie d'un jeu complet d'exemples couvrant toutes les ressources qui peuvent confirmer, exiger, demander ou accorder des autorisations de sécurité d'accès au code.
Ce module vous apporte des informations complètes sur le fonctionnement interne de la sécurité d'accès au code et couvre les évaluations de stratégie, les niveaux de stratégie, l'attribut APTCA, le code privilégié, les demandes d'autorisation, l'autorisation de code, les demandes de liaison et les assertions.
Il explique les trois principaux avantages de la sécurité d'accès au code et montre comment l'utiliser pour :
-
limiter ce que votre code peut faire ;
Par exemple, si vous développez un assembly qui effectue une E/S de fichier, vous pouvez utiliser la sécurité d'accès au code pour limiter les accès de votre code à des fichiers et des répertoires spécifiques. Ceci restreint les possibilités pour un pirate de forcer votre code pour accéder à des fichiers arbitraires. -
restreindre le code pouvant appeler votre code ;
Par exemple, vous pouvez souhaiter que votre assembly ne puisse être appelé que par un autre code développé par votre entreprise. Pour ce faire, utilisez le composant de clé publique du nom sûr d'un assembly pour appliquer ce genre de restriction. Ceci empêche un code malveillant d'appeler votre code. -
identifier le code.
Pour gérer efficacement la stratégie de sécurité d'accès au code et limiter ce que le code peut faire, ce dernier doit pouvoir être identifié. La sécurité d'accès au code utilise des preuves, telles que le nom sûr ou l'URL d'un assembly ou son hachage calculé pour identifier le code (assemblys).
Objectifs
Ce module vous permettra d'effectuer les opérations suivantes :
-
apprendre comment fonctionne la sécurité d'accès au code et ce qu'est un code privilégié ;
-
utiliser la sécurité d'accès au code pour restreindre un code qui doit effectuer des E/S de fichier, des accès aux données et accéder au journal des événements, au Registre, aux services d'annuaire, aux variables d'environnement, aux services Web, aux sockets et au DNS ;
-
appliquer l'attribut APTCA en toute sécurité et en toute efficacité ;
-
demander des autorisations et autoriser le code ;
-
utiliser le code privilégié en sandbox ;
-
savoir quand utiliser ou ne pas utiliser des demandes de liaison ;
-
savoir quand confirmer ou ne pas confirmer des demandes d'autorisation ;
-
utiliser des demandes et des exigences d'autorisation de manière efficace ;
-
utiliser la sécurité d'accès au code pour améliorer davantage la sécurité du code appelant non géré, à l'aide de la sérialisation et de délégués.
S'applique à
Ce module s'applique aux produits et technologies suivants :
-
Microsoft Windows Server 2000 et 2003 ;
-
Microsoft .NET Framework 1.1 ;
-
ASP.NET 1.1.
Explication de la sécurité d'accès au code
Pour utiliser de manière efficace la sécurité d'accès au code, vous devez avoir de bonnes bases, sur la terminologie, par exemple, et savoir comment la stratégie est évaluée. Pour de plus amples informations sur la sécurité d'accès au code, reportez-vous à la section « Ressources supplémentaires » à la fin de ce module. Si la sécurité d'accès au code vous est déjà familière, vous pouvez sauter cette section et passer directement à la section « APTCA » (AllowPartiallyTrustedCallersAttribute) plus loin dans ce module.
La sécurité d'accès au code est constituée des éléments suivants :
-
code ;
-
preuve ;
-
autorisations ;
-
stratégie ;
-
groupes de codes.
Code
Tout code géré est sujet à la sécurité d'accès au code. Lorsqu'un assembly est chargé, un jeu d'autorisations d'accès au code lui est octroyé, qui détermine les types de ressources auxquels il peut accéder et les types d'opérations privilégiées qu'il peut effectuer. Le système de sécurité Microsoft .NET Framework utilise des preuves afin d'authentifier (identifier) le code pour accorder des autorisations.
Remarque : un assembly est l'unité de configuration et de confiance pour la sécurité d'accès au code. La totalité du code d'un même assembly se voit accorder la même autorisation et est de ce fait approuvée de manière uniforme.
Preuve
La preuve est utilisée par le système de sécurité .NET Framework pour identifier les assemblys. La stratégie de sécurité d'accès au code utilise des preuves pour faciliter l'octroi des bonnes autorisations à l'assembly correct. Une preuve liée à l'emplacement inclut les éléments suivants :
-
URL : adresse URL à partir de laquelle l'assembly a été obtenu. Il s'agit de l'URL du code base sous sa forme brute, par exemple, http://webserver/vdir/bin/assembly.dll ou file://C:/directory1/directory2/assembly.dll.
-
Site : site à partir duquel l'assembly a été obtenu, par exemple, http://webserver. Le site est dérivé de l'URL du code base.
-
Répertoire de l'application : répertoire de base destiné à l'application en cours d'exécution.
-
Zone : zone à partir de laquelle l'assembly a été obtenu, par exemple, intranet local or Internet. La zone est également dérivée de l'URL du code base.
Une preuve liée à l'auteur inclut les éléments suivants :
-
Nom sûr : ceci s'applique aux assemblys dotés d'un nom sûr. Les noms sûrs constituent un moyen de signer numériquement un assembly à l'aide d'une clé privée.
-
Éditeur : signature Authenticode, basée sur le certificat X.509 utilisé pour signer le code, et représentant l'entreprise de développement.
Important : la preuve de l'éditeur (signature Authenticode) est ignorée par l'hôte ASP.NET et ne peut de ce fait être utilisée pour configurer la stratégie de sécurité d'accès au code pour les applications Web côté serveur. Cette preuve est principalement utilisée par l'hôte Internet Explorer.
-
Hachage : le hachage d'assembly est basé sur le contenu général de l'assembly et permet de détecter une compilation spécifique d'un morceau de code, indépendamment du numéro de version. Ceci est utile pour détecter les changements d'assemblys tiers (sans numéro de version mis à jour) que vous n'avez pas testés et dont vous n'avez pas autorisé l'utilisation dans votre génération.
Autorisations
Les autorisations représentent les droits permettant au code d'accéder à une ressource sécurisée ou d'effectuer une opération privilégiée. Le .NET Framework fournit des autorisations d'accès au code et des autorisations d'identité de code. Les autorisations d'accès au code englobent la possibilité d'accéder à une ressource particulière ou d'effectuer une opération privilégiée. Les autorisations d'identité de code sont utilisées pour limiter l'accès au code, en fonction d'un aspect de l'identité du code appelant, tel que son nom sûr.
Des autorisations sont accordées à votre code par la stratégie de sécurité d'accès au code qui est configurée par l'administrateur. Un assembly peut également affecter le jeu d'autorisations accordé au final via les demandes d'autorisation. Ensemble, la stratégie de sécurité d'accès au code et les demandes d'autorisation déterminent ce que votre code peut faire. Par exemple, le code doit disposer des autorisations FileIOPermission pour accéder au système de fichiers et RegistryPermission pour accéder au Registre. Pour plus d'informations sur les demandes d'autorisation, reportez-vous à la section « Demande d'autorisations » plus loin dans ce module.
Remarque : des jeux d'autorisations sont utilisés pour regrouper les autorisations et faciliter l'administration.
Autorisations restreintes et illimitées
Les autorisations peuvent être restreintes ou illimitées. Par exemple, dans son état illimité, l'autorisation FileIOPermission permet au code de lire ou d'écrire sur n'importe quelle partie du système de fichiers. Dans un état restreint, elle peut ne permettre au code que de lire les fichiers d'un répertoire spécifique.
Demandes impératives
Si vous utilisez une classe de la bibliothèque de classes .NET Framework pour accéder à une ressource ou effectuer une autre opération privilégiée, la classe émet une demande d'autorisation afin de s'assurer que votre code et que tout code appelant le vôtre sont autorisés à accéder à la ressource. Une demande d'autorisation contraint l'exécution à revenir en arrière dans la pile des appels (frame de pile par frame de pile), examinant les autorisations de chaque appelant de la pile. S'il s'avère qu'un appelant ne dispose pas de l'autorisation requise, une exception SecurityException est générée.
Demandes de liaison
Une demande de liaison n'effectue pas un parcours intégral de la pile. Elle ne vérifie que l'appelant immédiat, une frame de pile plus bas dans la pile des appels. Les demandes de liaison induisent donc des risques supplémentaires pour la sécurité. Vous devez donc être particulièrement attentif aux attaques par leurre.
Remarque : dans une attaque par leurre, un code malveillant accède aux ressources et aux opérations affichées par votre assembly, en appelant votre code au moyen d'un assembly intermédiaire approuvé.
Pour plus d'informations sur l'utilisation correcte des demandes de liaison, reportez-vous à la section « Demandes de liaison » plus loin dans ce module.
Méthodes Assert, Deny et PermitOnly
Les classes d'autorisation d'accès au code prennent en charge les méthodes Assert, Deny et PermitOnly. Vous pouvez utiliser ces méthodes pour modifier le comportement de parcours de pile d'une demande d'autorisation. Elles sont appelées modificateurs de parcours de la pile.
Un appel de la méthode Assert entraîne l'arrêt du parcours de la pile visant à rechercher une autorisation de correspondance au site de l'appel Assert. Ceci est plus souvent utilisé pour le code privilégié en sandbox. Pour plus d'informations, reportez-vous à la section « Assert et RevertAssert » plus loin dans ce module.
Un appel à la méthode Deny rejette tout parcours de pile qui l'atteint avec une autorisation de correspondance. Si vous appelez un code non sécurisé, vous pouvez utiliser la méthode Deny pour restreindre les capacités du code que vous appelez.
Un appel de la méthode PermitOnly rejette tout parcours de pile non correspondant. Tout comme la méthode Deny, elle tend à être utilisée peu fréquemment, mais peut être utilisée pour restreindre les actions d'un code non sécurisé que vous pouvez appeler.
Stratégie
La stratégie de sécurité d'accès au code est configurée par les administrateurs et elle détermine les autorisations accordées aux assemblys. La stratégie peut être établie aux quatre niveaux suivants :
-
Entreprise : utilisé pour appliquer la stratégie au niveau de l'entreprise globale.
-
Machine : utilisé pour appliquer la stratégie au niveau de la machine.
-
Utilisateur : utilisé pour appliquer la stratégie selon l'utilisateur.
-
Domaine d'application : utilisé pour configurer le domaine d'application dans lequel un assembly est chargé.
ASP.NET implémente une stratégie de domaine d'application qui permet de configurer la stratégie de sécurité d'accès au code pour les applications et les services Web. Pour plus d'informations sur la stratégie de domaine d'application ASP.NET, reportez-vous au module 9, « Utilisation de la sécurité d'accès au code avec ASP.NET ».
Les paramètres de la stratégie sont conservés dans les fichiers de configuration XML. Les trois premiers niveaux de la stratégie (Entreprise, Machine et Utilisateur) peuvent être configurés à l'aide de l'outil .NET Framework Configuration qui se trouve dans le groupe de programmes Outils d'administration ou de l'utilitaire de ligne de commande Caspol.exe. La stratégie au niveau du domaine d'application ASP.NET doit être éditée à l'aide d'un éditeur texte ou XML.
Pour plus d'informations sur les fichiers de stratégie et leur emplacement, reportez-vous au module 19 « Sécurisation de votre application ASP.NET et de vos services Web ».
Groupes de codes
Chaque fichier de stratégie contient une collection hiérarchique de groupes de codes. Ces groupes de codes sont utilisés pour attribuer des autorisations aux assemblys. Un groupe de codes est constitué des deux éléments suivants :
-
Une condition d'appartenance : elle est basée sur la preuve, par exemple la zone ou le nom sûr d'un assembly.
-
Un jeu d'autorisations : les autorisations contenues dans le jeu sont accordées aux assemblys dont la preuve correspond à la condition d'appartenance.
Comment cela fonctionne-t-il ?
La figure 8.1 est une présentation simplifiée de la sécurité d'accès au code.
Figure 8.1
Sécurité d'accès au code Vue simplifiée
Les étapes illustrées à la figure 8.1 sont résumées ci-dessous.
-
Un assembly est chargé.
Cette opération est effectuée par l'hôte d'un domaine d'application. Sur un serveur Web chargeant un assembly d'application Web, il s'agit de l'hôte ASP.NET.
-
La preuve est apportée par l'assembly et présentée par l'hôte.
-
Elle est évaluée par rapport à la stratégie de sécurité définie.
-
De cette évaluation de stratégie de sécurité émanent un ou plusieurs jeux d'autorisations désignés qui définissent l'octroi d'autorisation pour l'assembly.
Remarque : un assembly peut inclure des demandes d'autorisation qui peuvent réduire davantage l'octroi d'autorisations.
-
Le code contenu dans l'assembly demande impérativement l'autorisation appropriée avant d'accéder à une ressource restreinte ou d'effectuer une opération privilégiée.
Toutes les classes de base de .NET Framework qui accèdent à des ressources ou effectuent des opérations privilégiées contiennent les demandes d'autorisation appropriées. Par exemple, la classe FileStream demande l'autorisation FileIOPermission, la classe Registry demande l'autorisation RegistryPermission, etc.
-
Si l'autorisation demandée a été accordée à l'assembly (et à ses appelants), l'opération peut avoir lieu. Dans le cas contraire, une exception de sécurité est générée.
Comment la stratégie est-elle évaluée ?
Lorsqu'une preuve est traitée par le moteur de stratégie, il en ressort un jeu d'autorisations qui définit le jeu d'autorisations accordé à un assembly. L'accord de stratégie est calculé à chaque niveau de la hiérarchie de stratégie : Entreprise, Machine, Utilisateur et Domaine d'application. Les accords de stratégie émanant de chaque niveau sont ensuite combinés à l'aide d'une opération d'intersection pour aboutir à l'accord de stratégie final. Une intersection est utilisée pour garantir que la stratégie située plus bas dans la hiérarchie ne peut pas ajouter des autorisations non accordées à un niveau supérieur. Ceci empêche un utilisateur individuel ou un domaine d'application d'octroyer des autorisations supplémentaires qui ne sont pas accordées par l'administrateur de l'entreprise.
La figure 8.2 montre comment l'opération d'intersection indique que les autorisations résultantes sont déterminées par tous les niveaux de la hiérarchie de stratégie.
Figure 8.2
Intersection de stratégie entre les niveaux de stratégie
Dans la figure 8.2, vous pouvez voir que l'opération d'intersection assure que seules les autorisations accordées par chaque niveau font partie de l'accord d'autorisation final.
En quoi les demandes d'autorisation affectent-elles l'accord de stratégie ?
Vous pouvez ajouter des attributs de sécurité à votre assembly pour spécifier ses exigences d'autorisation. Vous pouvez spécifier le jeu d'autorisations minimal dont votre assembly doit disposer pour s'exécuter. Ceci n'affecte en rien l'accord d'autorisations. Vous pouvez également spécifier les autorisations facultatives dont votre assembly pourrait faire usage, mais qui ne sont pas absolument requises et les autorisations que vous souhaitez refuser. Les autorisations refusées sont celles que vous souhaitez ne jamais voir octroyées à votre assembly, même si elles sont accordées par la stratégie de sécurité.
Si vous demandez des autorisations facultatives, l'intersection des autorisations optionnelles et minimales combinées est effectuée dans l'accord de stratégie pour la réduire davantage. Ensuite, toutes les autorisations refusées spécifiquement sont retirées de l'accord de stratégie. Ceci se résume par la formule suivante dans laquelle PG correspond à l'accord de stratégie de la stratégie de sécurité définie par l'administrateur et P min, P opt et P refused les demandes d'autorisation ajoutées à l'assembly par le développeur.
Autorisations résultantes = (PG n (P min U P opt )) - P refused
Pour plus d'informations sur le mode d'utilisation des demandes d'autorisation, leurs implications et quand les utiliser, reportez-vous à la section « Demande d'autorisations » plus loin dans ce module.
Évaluation de la stratégie au niveau de la stratégie
Un fichier de stratégie distinct à chaque niveau spécifique est constitué d'un classement hiérarchique des groupes de codes. Ces groupes de codes incluent les conditions d'appartenance utilisées pour déterminer à quels assemblys ils s'appliquent et les jeux d'autorisations utilisés pour déterminer les autorisations qui doivent être accordées aux assemblys correspondants. Une structure hiérarchique permet à plusieurs jeux d'autorisations d'être accordés à un assembly et elle permet à la stratégie de sécurité de prendre en charge les opérateurs logiques AND et OR. Ainsi par exemple, considérons l'exemple de stratégie de sécurité illustrée à la figure 8.3.
Figure 8.3
Groupes de codes hiérarchiques à un seul niveau de stratégie
Remarque : le groupe de codes Tous les codes est un groupe de codes spécial qui correspond à tous les assemblys. Il forme la racine de la stratégie de sécurité et n'accorde pas lui-même d'autorisations, car il est associé au jeu d'autorisations nommé Rien.
Considérons les autorisations accordées en fonction de la stratégie de sécurité illustrée à la figure 8.3.
-
Tout assembly émanant de Mon_Poste_de_travail (tout assembly installé localement) reçoit les autorisations définies par le jeu d'autorisations FullTrust. Il s'agit d'un jeu d'autorisations intégré, défini lors de l'installation de .NET Framework et qui représente le jeu illimité de toutes les autorisations.
-
Les assemblys créés par l'entreprise 1 et émanant de la zone intranet reçoivent les autorisations définies par le jeu d'autorisations intégré LocalIntranet_Zone et le jeu d'autorisations personnalisé Comp1PSet.
-
Les assemblys créés par l'entreprise 2 reçoivent les autorisations définies par le jeu d'autorisations personnalisé Comp2PSet.
-
Tout assembly téléchargé de a.b.c.com reçoit les autorisations définies par le jeu d'autorisations personnalisé ABCPSet.
Remarque : si la condition d'appartenance d'un groupe de codes spécifique n'est pas satisfaite, aucun de ses enfants n'est évalué.
Groupes de codes Exclusif et Niveau final
Le traitement hiérarchique et le parcours de la stratégie peuvent être réglés à l'aide d'une paire d'attributs spécifiés au niveau du groupe de codes, tous deux pouvant être définis via l'outil .NET Framework Configuration. Il s'agit de :
-
Exclusif
Ceci indique qu'aucun autre groupe de codes frère ne doit être associé à ce groupe de codes. Pour marquer un groupe de codes comme étant Exclusif, sélectionnez l'option Ce niveau de stratégie ne bénéficiera que des autorisations du jeu d'autorisations associé à ce groupe de codes dans l'outil .NET Framework Configuration. -
Niveau final
Ceci indique que toutes les stratégies de niveau inférieur doivent être ignorées. Pour marquer un groupe de codes comme étant de Niveau final, sélectionnez l'option Les niveaux de stratégie en dessous de ce niveau ne seront pas évalués dans l'outil .NET Framework Configuration. Par exemple, si un groupe de codes correspondant dans la stratégie de machine est marqué comme étant de Niveau final, les paramètres de stratégie du fichier de stratégie utilisateur sont ignorés.Remarque : la stratégie au niveau du domaine d'application, par exemple, la stratégie ASP.NET pour les applications Web côté serveur, est toujours évaluée sans égard au paramètre de niveau final.
APTCA
Un assembly portant un nom sûr ne peut pas être appelé par un assembly de confiance partielle (assembly qui n'est pas de confiance totale), à moins que l'assembly portant le nom sûr ne contienne l'attribut AllowPartiallyTrustedCallersAttribute (APTCA) comme suit :
[assembly: AllowPartiallyTrustedCallersAttribute()]
Il s'agit d'une stratégie de réduction des risques conçue pour garantir que votre code ne peut pas être affiché par inadvertance à un code de confiance partielle (potentiellement malveillant). Le CLR (Common Language Runtime) ajoute automatiquement une demande de liaison du jeu d'autorisations FullTrust à tous les membres accessibles publiquement sur les types dans un assembly portant un nom sûr. Si vous incluez l'attribut APTCA, vous supprimez cette demande de liaison.
Éviter l'utilisation de l'attribut APTCA
Si vous utilisez l'attribut APTCA, votre code est immédiatement plus vulnérable aux attaques et de ce fait, il est particulièrement important de revoir votre code à la recherche de failles de sécurité. Utilisez l'attribut APTCA uniquement si cela s'avère absolument nécessaire.
Dans le contexte des applications Web côté serveur, utilisez l'attribut APTCA chaque fois que votre assembly doit prendre en charge des appelants de confiance partielle. Ce cas peut se présenter dans les circonstances suivantes :
-
Votre assembly doit être appelé par une application Web de confiance partielle. Il s'agit d'applications pour lesquelles le niveau de confiance <trust> est défini à autre chose que totale. Pour plus d'informations sur les applications Web de confiance partielle et l'utilisation de l'attribut APTCA dans ce cas, reportez-vous au module 9, « Utilisation de la sécurité d'accès au code avec ASP.NET ».
-
Votre assembly doit être appelé par un autre assembly auquel des autorisations restreintes ont été accordées par l'administrateur de sécurité d'accès au code.
-
Votre assembly doit être appelé par un autre assembly qui refuse des autorisations spécifiques à l'aide de SecurityAction.RequestRefuse ou SecurityAction.RequestOptional. Ceci fait de l'assembly appelant un assembly de confiance partielle.
-
Votre assembly doit être appelé par un autre assembly qui utilise un modificateur de parcours de pile (tel que Deny ou PermitOnly) pour limiter le code en aval.
Diagnostic des problèmes d'attribut APTCA
Si vous tentez d'appeler un assembly portant un nom sûr qui n'est pas marqué avec l'attribut APTCA d'un code de confiance partielle, telle qu'une application Web de confiance partielle, une exception identique à celle illustrée à la figure 8.4 se produit. Notez que les détails de l'exception ne fournissent aucun détail des autorisations et indiquent simplement que les autorisations requises (dans ce cas, FullTrust) ne peuvent pas être acquises à partir de l'assembly appelant. Dans ce cas, le texte de description quelque peu ambigu signifie que l'erreur s'est produite du fait que le niveau de confiance <trust> de l'application était différent de Totale (Full).
Figure 8.4
Résultat d'un code de confiance partielle appelant un assembly portant un nom sûr
Pour résoudre cette exception, le code appelant doit être totalement approuvé (FullTrust) ou l'assembly appelé doit comporter l'attribut APTCA. Notez que les types individuels contenus dans un assembly portant l'attribut APTCA peuvent requérir des appelants de confiance totale du fait qu'ils incluent une demande de liaison explicite ou une demande standard de confiance totale, comme le montrent les exemples ci-dessous.
[PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")] [PermissionSet(SecurityAction.Demand, Unrestricted=true)]
Code privilégié
Lorsque vous concevez et générez des assemblys sécurisés, vous devez pouvoir identifier le code privilégié. Ceci a d'importantes implications pour la sécurité d'accès au code. Le code privilégié est un code géré qui accède aux ressources sécurisées et effectue d'autres opérations liées à la sécurité, tel que l'appel de code non géré à l'aide de la sérialisation ou de la réflexion. Ce code est privilégié car la sécurité d'accès au code doit lui accorder des autorisations spécifiques pour qu'il puisse fonctionner.
Ressources privilégiées
Les ressources privilégiées pour lesquelles votre code requiert des autorisations de sécurité d'accès au code spécifiques sont indiquées dans le tableau 8.1.
Tableau 8.1 : Ressources sécurisées et autorisations associées
| Ressources sécurisées | Autorisation requise |
|---|---|
| Accès aux données | SqlClientPermission |
| Services d'annuaire | DirectoryServicesPermission |
| Bases de données DNS | DnsPermission |
| Journal d'événements | EventLogPermission |
| Variables d'environnement | EnvironmentPermission |
| Système de fichiers | FileIOPermission |
| Stockage isolé | IsolatedStoragePermission |
| Files d'attente de messages | MessageQueuePermission |
| Compteurs de performance | PerformanceCounterPermission |
| Imprimantes | PrinterPermission |
| Registre | RegistryPermission |
| Sockets | SocketPermission |
| Services Web (et autres ressources Internet HTTP) | WebPermission |
Opérations privilégiées
Les opérations privilégiées sont indiquées dans le tableau 8.2, avec les autorisations associées requises par le code appelant.
Tableau 8.2 : Opérations privilégiées et autorisations associées
| Opération | Autorisation requise |
|---|---|
| Création et contrôle des domaines d'application | SecurityPermission avec |
| Spécification des domaines d'application de la stratégie | SecurityPermission avec |
| Assertion des autorisations de sécurité | SecurityPermission avec |
| Création et manipulation de preuves | SecurityPermission avec |
| Création et manipulation des principaux objets | SecurityPermission avec |
| Configuration des types et des canaux d'accès distant | SecurityPermission avec |
| Manipulation de la stratégie de sécurité | SecurityPermission avec |
| Sérialisation | SecurityPermission avec |
| Opérations de thread | SecurityPermission avec |
| Réflexion | ReflectionPermission |
| Appel de code non géré | SecurityPermission avec |
Demande d'autorisations
Lors de la conception et du développement de vos assemblys, créez la liste de toutes les ressources auxquelles votre code accède et de toutes les opérations privilégiées qu'il effectue. Au moment du déploiement, il se peut que l'administrateur ait besoin de ces informations pour configurer correctement la stratégie de sécurité d'accès au code et pour identifier les problèmes liés à la sécurité.
La meilleure façon de communiquer les conditions d'autorisation requises de votre code est d'utiliser les attributs de sécurité déclaratifs au niveau de l'assembly pour spécifier les autorisations minimales. Ces informations figurent normalement dans les fichiers Assemblyinfo.cs ou Assemblyinfo.vb. Ceci permet à l'administrateur ou au consommateur de votre assembly de vérifier les autorisations requises à l'aide de l'outil Permview.exe.
RequestMinimum
Utilisez la méthode SecurityAction.RequestMinimum avec des attributs d'autorisation déclaratifs pour spécifier le jeu minimal d'autorisations que votre assembly doit exécuter. Par exemple, si votre assembly doit accéder au Registre, mais ne doit extraire que des données de configuration d'une clé spécifique, utilisez un attribut du type suivant :
[assembly: RegistryPermissionAttribute(
SecurityAction.RequestMinimum,
Read=@"HKEY_LOCAL_MACHINE\SOFTWARE\VotreApp")]
Si d'emblée, vous savez que votre code s'exécutera dans un environnement de confiance totale et que le jeu complet d'autorisations illimitées lui sera accordé, l'utilisation de la méthode RequestMinimum est moins importante. Cependant, il est préférable de spécifier les conditions d'autorisation requises pour votre assembly.
Remarque : les attributs d'autorisation acceptent une liste de propriétés et de valeurs de propriété séparées par des virgules, après les arguments de constructeur obligatoires. Ils sont utilisés pour initialiser l'objet d'autorisation sous-jacent. Une méthode rapide pour trouver quels noms de propriété sont pris en charge consiste à utiliser Ildasm.exe sur l'assembly contenant le type d'attribut d'autorisation.
RequestOptional
Si vous utilisez la méthode SecurityAction.RequestOptional, aucune autre autorisation, excepté celles spécifiées avec SecurityAction.RequestMinimum et SecurityAction.RequestOptional ne sera accordée à votre assembly, même si sinon des autorisations supplémentaires lui auraient été attribuées par la stratégie de sécurité d'accès au code.
RequestRefused
La méthode SecurityAction.RequestRefuse permet de s'assurer que la stratégie de sécurité d'accès au code n'accorde pas à l'assembly des autorisations qu'il ne requiert pas. Par exemple, si votre assembly n'appelle pas de code non géré, vous pouvez utiliser l'attribut suivant pour vous assurer que la stratégie de sécurité d'accès au code n'accorde pas à votre assembly l'autorisation de code non géré :
[assembly: SecurityPermissionAttribute(SecurityAction.RequestRefuse,
UnmanagedCode=true)] Implications de l'utilisation de RequestOptional ou RequestRefuse
Si vous utilisez RequestOptional, l'intersection du jeu d'autorisations spécifiées avec RequestOptional et RequestMinimum est faite avec les autorisations accordées à votre assembly par la stratégie. Ceci signifie que toutes les autres autorisations en dehors des jeux RequestOptional et RequestMinimum sont supprimées des autorisations accordées à votre assembly. En outre, si vous utilisez RequestRefuse, les autorisations refusées sont également supprimées du jeu d'autorisations accordées à votre assembly.
Ainsi, si vous utilisez RequestOptional ou RequestRefuse, votre assembly devient un assembly de confiance partielle, ceci ayant des répercussions lorsque vous appelez d'autres assemblys. Tenez compte des remarques suivantes pour décider si vous devez utiliser SecurityAction.RequestOptional ou SecurityAction.RequestRefuse :
-
Ne les utilisez pas si vous devez appeler directement un assembly portant un nom sûr sans AllowPartiallyTrustedCallersAttribute (APTCA) car ceci vous empêcherait de l'appeler.
De nombreux assemblys .NET Framework portant un nom sûr contiennent des types qui ne prennent pas en charge les appelants de confiance partielle et n'incluent pas l'attribut APTCA. Pour plus d'informations et la liste des assemblys prenant en charge les appelants de confiance partielle, reportez-vous à la section « Développement d'applications Web de confiance partielle » du module 9, « Utilisation de la sécurité d'accès au code avec ASP.NET ».
Si vous devez appeler des assemblys portant des noms sûrs sans utiliser l'attribut APTCA, informez les administrateurs responsables de l'installation de votre code que la stratégie de sécurité d'accès au code doit accorder une confiance totale à votre code pour qu'il fonctionne correctement.
-
S'il ne vous est pas nécessaire d'accéder à des assemblys APTCA, ajoutez des demandes d'autorisation pour refuser celles dont votre assembly n'a pas besoin. Testez préalablement votre code pour vous assurer qu'il n'a réellement pas besoin de ces autorisations.
-
Si le code en aval requiert l'autorisation que vous avez refusée, une méthode entre vous et le code en aval doit confirmer l'autorisation. Sinon, une exception SecurityException est générée lorsque le parcours de pile atteint votre code.
Autorisation du code
La sécurité d'accès au code permet d'autoriser le code qui appelle votre assembly. Ceci réduit les risques qu'un code malveillant ne parvienne à appeler votre code. Par exemple, vous pouvez utiliser les autorisations d'identité pour limiter le code appelant en fonction des preuves d'identité, telles que le composant de clé publique de son nom sûr. Vous pouvez également utiliser des demandes explicites d'autorisation d'accès au code pour vous assurer que le code appelant votre assembly dispose des autorisations nécessaires pour accéder à la ressource ou effectuer l'opération privilégiée affichée par votre assembly.
Généralement, il n'est pas nécessaire de demander explicitement des autorisations d'accès au code. Les classes de .NET Framework le font pour vous et une double demande est inutile. Cependant, il y a des cas où vous devez émettre des demandes explicites, par exemple si votre code affiche une ressource personnalisée par l'utilisation d'un code non géré ou si votre code accède à des données mises en cache. Pour autoriser le code, procédez comme suit :
-
limitez le code pouvant appeler votre code ;
-
limitez l'héritage ;
-
envisagez la protection des données mises en cache ;
-
protégez les ressources personnalisées à l'aide d'autorisations personnalisées.
Restriction du code pouvant appeler votre code
Une méthode marquée comme publique peut être appelée par n'importe quel code en dehors de l'assembly courant. Pour restreindre davantage encore le code pouvant appeler vos méthodes, vous pouvez utiliser une demande d'autorisation d'identité de sécurité d'accès au code comme le montre l'exemple ci-dessous.
public sealed class Utility
{
// Bien que SomeOperation() soit une méthode publique, la demande d'autorisation
// suivante signifie qu'elle ne peut être appelée que par des assemblys
// associés à la clé publique indiquée.
[StrongNameIdentityPermission(SecurityAction.LinkDemand,
PublicKey="00240000048...97e85d098615")]
public static void SomeOperation() {}
}
Le code ci-dessus illustre une demande de liaison. Ceci entraîne l'autorisation de l'appelant immédiat. Ainsi, votre code est ouvert aux attaques par leurre dans lesquelles un assembly malveillant peut potentiellement accéder aux ressources protégées ou aux opérations fournies par votre assembly via un assembly intermédiaire approuvé portant le nom sûr spécifié.
Selon la nature de la fonctionnalité fournie par votre classe, il se peut vous deviez demander une autre autorisation afin d'autoriser le code appelant en plus de l'utilisation de la demande de liaison basée sur l'identité. Vous pouvez également envisager d'utiliser une demande complète, associée à l'autorisation StrongNameIdentityPermission, bien que ceci présume que tout le code de la pile des appels est signé à l'aide d'un nom sûr utilisant la même clé privée.
Remarque : l'émission d'une demande de parcours de pile complète pour StrongNameIdentityPermission ne fonctionne pas si votre assembly est appelé par une application ou un service Web. Ceci est dû au fait qu'il n'est pas possible d'attribuer un nom sûr aux classes compilées dynamiquement, associées aux services ou aux applications Web ASP.NET.
-
Pour extraire une clé publique d'un assembly, procédez comme suit :
-
Exécutez la commande suivante pour obtenir une représentation hexadécimale d'une clé publique d'un assembly :
secutil -hex -strongname yourassembly.dll
-
-
Pour extraire la clé publique d'un fichier de paire de clés, procédez comme suit :
-
Générez le fichier de paire de clés à l'aide de la commande suivante :
sn -k keypairfile
-
Extrayez la clé publique du fichier de paire de clés :
sn -p keypairfile publickeyfile
-
Vous obtenez la représentation hexadécimale de la clé publique suivante :
sn -tp publickeyfile < publickeyhex.dat
-
Restriction de l'héritage
Si votre classe a été conçue comme une classe de base, vous pouvez limiter les autres codes autorisés à dériver de votre classe en utilisant une demande d'héritage associée à une autorisation StrongNameIdentityPermission comme le montre l'exemple ci-dessous. Ceci empêche l'héritage de votre classe à partir d'un assembly non signé à l'aide de la clé privée correspondant à la clé publique contenue dans la demande.
// La demande d'héritage suivante garantit que seul le code situé dans
// l'assemblage associé à la clé publique indiquée (qui fait partie du nom fort de l'assembly)
// peut sous-classer SomeRestrictedClass
[StrongNameIdentityPermission(SecurityAction.InheritanceDemand,
PublicKey="00240000048...97e85d098615")]
public class SomeRestrictedClass
{
} Étude de la protection des données mises en cache
Si vous accédez à une ressource à l'aide de l'une des classes de .NET Framework, une demande d'autorisation appropriée au type de ressource concerné est émise par la classe. Si à des fins de performances, vous mettez ultérieurement les données en cache, vous devez envisager d'émettre une demande explicite d'autorisation d'accès au code afin d'accéder aux données mises en cache. Ceci garantit que le code appelant est autorisé à accéder au type de ressource spécifique. Par exemple, si vous lisez les données d'un fichier, que vous mettez ensuite en cache et que vous souhaitez vous assurer que le code appelant est autorisé, émettez une demande FileIOPermission comme le montre l'exemple ci-dessous.
// La demande suivante part du principe que les données mises en cache ont été initialement extraites de
// C:\RépertQuelconque\FichierQuelconque.dat
new FileIOPermission(FileIOPermissionAccess.Read,
@"C:\SomeDir\SomeFile.dat").Demand();
// Maintenant, accéder au cache et renvoyer les données à l'appelant Protection des ressources personnalisées à l'aide d'autorisations personnalisées
Si vous affichez une ressource ou une opération à l'aide d'un code non géré, vous devez mettre votre code wrapper en sandbox et envisager de demander une autorisation personnalisée pour autoriser le code appelant.
L'autorisation personnalisée est automatiquement accordée aux appelants de confiance totale, à condition que le type d'autorisation implémente l'interface IUnrestrictedPermission. Les appelants de confiance partielle n'auront pas l'autorisation à moins qu'elle leur ait été spécifiquement accordée par la stratégie de sécurité d'accès au code. Ceci garantit qu'un code non approuvé ne peut pas appeler votre assembly pour accéder aux ressources personnalisées qu'il affiche. La mise en sandbox signifie également que vous n'êtes pas obligé d'accorder la puissante autorisation UnmanagedCodePermission à tout code devant appeler le vôtre.
Pour plus d'informations sur l'appel de code non géré, reportez-vous à la section « Code non géré » de ce module. Pour un exemple d'implémentation d'une autorisation personnalisée, reportez-vous à la section « Procédure : création d'une autorisation de cryptage personnalisée » de ce guide.
Demandes de liaison
Une demande de liaison diffère d'une demande d'autorisation standard de par le fait que l'environnement d'exécution demande des autorisations uniquement à l'appelant immédiat et n'effectue pas un parcours complet de la pile. Les demandes de liaison sont effectuées au moment de la compilation JIT et ne peuvent être spécifiées que de manière déclarative.
Envisagez avec précaution l'utilisation d'une demande de liaison car celle-ci entraîne aisément l'introduction de failles de sécurité. Si vous utilisez des demandes de liaison, tenez compte des éléments suivants :
-
attaques par leurre ;
-
performances et demandes de liaison ;
-
appels de méthodes avec des demandes de liaison ;
-
mélange de demandes de liaison aux niveaux de la classe et de la méthode ;
-
interfaces et demandes de liaison ;
-
structures et demandes de liaison ;
-
méthodes virtuelles et demandes de liaison.
Attaques par leurre
Si vous protégez un code avec une demande de liaison, il est vulnérable aux attaques par leurre, dans lesquelles un code malveillant obtient l'accès à la ressource ou à l'opération affichée par votre code via un intermédiaire de confiance comme illustré à la figure 8.5.
Figure 8.5
Exemple d'attaque par leurre avec demandes de liaison
Dans la figure 8.5, les méthodes de l'assembly X qui accèdent à une ressource sécurisée sont protégées par une demande de liaison pour une clé publique spécifique (à l'aide d'une autorisation StrongNameIdentityPermission). Les assemblys A, B et C sont signés avec la clé privée qui correspond à la clé publique à laquelle fait confiance l'assembly X. Ainsi, ils peuvent appeler l'assembly X. Les assemblys A, B et C sont victimes d'une attaque par leurre s'ils ne demandent pas une preuve spécifique à leurs appelants avant d'effectuer des appels à l'assembly X. Par exemple, l'assembly D qui n'est pas signé avec la même clé privée ne peut pas appeler l'assembly X directement. Cependant, il peut accéder à l'assembly X via l'assembly de confiance A, si ce dernier ne contrôle pas ses appelants, via une autre demande de liaison ou via une demande complète.
Utilisez des demandes de liaison dans un assembly uniquement si vous croyez que les appelants de l'assembly n'exposent pas davantage sa fonctionnalité (par exemple, si l'appelant est une application, pas une bibliothèque) ou si vous savez qu'il suffit de vérifier l'identité de l'appelant immédiat par une demande d'autorisation d'identité.
Performances et demandes de liaison
Comparé aux autres problèmes de performances d'application Web, tels que la latence du réseau ou l'accès aux bases de données, le coût d'un parcours de pile est faible. N'utilisez pas de demande de liaison simplement à des fins de performances. Des demandes complètes fournissent un degré de sécurité bien plus grand.
Appels de méthodes avec des demandes de liaison
Si vous appelez une méthode protégée par une demande de liaison, seul votre code sera vérifié par la demande de liaison. Dans ce cas, vous devez vous assurer que votre code prend les mesures adéquates pour autoriser ses appelants, par exemple, en demandant une autorisation.
Mélange de demandes de liaison aux niveaux de la classe et de la méthode
Les demandes de liaison au niveau de la méthode supplantent les demandes de liaison au niveau de la classe. Par exemple, dans le fragment de code suivant, la demande de liaison pour FileIOPermission doit être répétée sur la déclaration de la méthode ou la demande de liaison EnvironmentPermission remplace la demande au niveau de la classe FileIOPermission.
[FileIOPermission(SecurityAction.LinkDemand, Unrestricted=true)]
public sealed class SomeClass
{
// La demande de liaison FileIOPermission illimitée doit être reformulée au niveau
// méthode si la méthode est assortie d'une autre demande de liaison.
// Sinon, cela signifie (dans cet exemple) que la demande de liaison
// EnvironmentPermission remplacerait
// la demande de liaison FileIOPermission de niveau classe
[FileIOPermission(SecurityAction.LinkDemand, Unrestricted=true)]
[EnvironmentPermission(SecurityAction.LinkDemand, Read="PATH")]
public void SomeMethod()
{
}
} Interfaces et demandes de liaison
Si votre classe implémente une interface et que l'une des implémentations de la méthode est dotée d'une demande de liaison, assurez-vous que la déclaration de la méthode sur la définition de l'interface dispose de la même demande de liaison. Sinon, il suffit à l'appelant d'appeler votre méthode via l'interface pour outrepasser la demande de liaison. L'exemple suivant en est une parfaite illustration :
public interface IMyInterface
{
// La demande de liaison présentée dans l'implémentation de méthode ci-dessous
// doit être répétée ici
void Method1();
}
public class MyImplementation : IMyInterface
{
// L'implémentation de méthode contient une demande de liaison mais pas l'interface
[SecurityPermission(SecurityAction.LinkDemand,
Flags=SecurityPermissionFlag.ControlPrincipal)]
public void Method1()
{
}
}
Avec le code suivant, l'appelant est sujet à la demande de liaison :
MyImplementation t = new MyImplementation(); t.Method1();
Avec le code suivant, l'appelant n'est pas sujet à la demande de liaison :
IMyInterface i = new MyImplementation(); i.Method1();
Structures et demandes de liaison
Les demandes de liaison n'empêchent pas la construction de structures par des appelants non dignes de confiance. Ceci est dû au fait que des constructeurs par défaut ne sont pas automatiquement générés pour des structures. Ainsi, la demande de liaison au niveau de la structure ne s'applique que si vous utilisez un constructeur explicite. Par exemple :
[SecurityPermission(SecurityAction.LinkDemand,
Flags=SecurityPermissionFlag.ControlPrincipal)]
public struct SomeStruct
{
// Ce constructeur explicite est protégé par la demande de liaison
public SomeStruct(int i)
{
field = i;
}
private int field;
}
Les deux lignes de code suivantes engendrent toutes deux une nouvelle structure avec la zone initialisée à zéro. Cependant, seule la première ligne qui utilise le constructeur explicite est sujette à une demande de liaison.
SomeStruct s = new SomeStruct(0); SomeStruct s = new SomeStruct();
La seconde ligne n'est pas sujette à une demande de liaison car aucun constructeur par défaut n'est généré. S'il s'agissait d'une classe et non d'une structure, le compilateur générerait un constructeur par défaut, annoté avec la demande de liaison spécifiée.
Méthodes virtuelles et demandes de liaison
Si vous utilisez une demande de liaison pour protéger une méthode de remplacement dans une classe dérivée, veillez à la placer également sur la méthode de classe de base virtuelle correspondante. Sinon, si le compilateur JIT voit une référence au type de classe de base sur laquelle il n'y a pas de demande de liaison, aucune demande de liaison n'est effectuée.
Assert et RevertAssert
Vous pouvez appeler la méthode CodeAccessPermission.Assert pour empêcher une demande de se propager au-delà de la frame de pile en cours. En utilisant Assert, vous vous portez garant de la loyauté des appelants à votre code. En raison des attaques par leurre potentielles, Assert doit être utilisé avec précaution.
Les assertions sont plus souvent utilisées pour le code privilégié en sandbox. Si vous développez du code qui appelle la méthode Assert, vous devez vous assurer que des mesures de sécurité alternatives sont en place pour autoriser le code appelant. Les recommandations suivantes permettent de minimiser les risques :
-
utiliser le schéma demande/assertion ;
-
réduire la durée d'assertion.
Utilisation du schéma Demande/Assertion
Demander une autorisation spécifique avant d'appeler la méthode Assert constitue un moyen efficace pour autoriser le code en amont. Parfois, vous pouvez demander un type d'autorisation intégrée pour autoriser le code appelant.
Souvent, si votre assembly expose une fonctionnalité qui n'est pas fournie par la bibliothèque de classes de .NET Framework, l'appel de l'API de protection des données (DPAPI) par exemple, vous devez développer une autorisation personnalisée et demander cette autorisation pour autoriser les appelants. Par exemple, vous pouvez développer une autorisation de cryptage personnalisée pour autoriser les appelants à un assembly de wrapper DPAPI géré. Demander cette autorisation, puis confirmer l'autorisation du code non géré, constitue un moyen efficace pour autoriser le code appelant.
Pour plus d'informations sur cette approche et sur le développement des autorisations personnalisées, reportez-vous à la section « Procédure : création d'une autorisation de cryptage personnalisée » de ce guide.
Réduction de la durée d'assertion
S'il vous suffit d'appeler la méthode Assert pour satisfaire les demandes d'une seule méthode en aval appelée par votre code, placez Assert immédiatement avant l'appel de méthode aval. Ensuite, appelez immédiatement RevertAssert pour maintenir la fenêtre d'assertion aussi petite que possible et vous assurer que tout code ultérieur appelé par votre méthode n'aboutit pas par erreur du fait que la méthode Assert est toujours activée.
La pratique courante vise à placer l'appel à RevertAssert dans un bloc de fin pour garantir qu'il est toujours appelé même dans le cas d'une exception.
Restriction du code
La restriction de code et la construction du code le moins privilégié reviennent à utiliser le principe du privilège le plus faible lorsque vous configurez les comptes utilisateur et de service. En limitant les autorisations de sécurité d'accès au code disponibles pour votre code, vous réduisez l'étendue de son utilisation malveillante.
Il existe deux moyens pour contraindre le code à limiter les ressources auxquelles il peut accéder, ainsi que les autres opérations privilégiées qu'il peut effectuer :
-
utiliser des autorisations de stratégie ;
-
utiliser des modificateurs du parcours de pile.
Utilisation des autorisations de stratégie
Vous pouvez configurer la stratégie de sécurité d'accès au code afin d'accorder un jeu d'autorisations restreintes à un assembly spécifique. Ceci restreint ses capacités à accéder aux ressources ou à effectuer des opérations privilégiées. Pour plus d'informations, reportez-vous à la section « Procédure : configuration de la stratégie de sécurité d'accès au code pour limiter un assembly » de ce guide.
Utilisation des modificateurs du parcours de pile
Vous pouvez utiliser les modificateurs de parcours de pile pour vous assurer que seules les autorisations spécifiques sont disponibles pour le code que vous appelez. Par exemple, vous pouvez utiliser SecurityAction.PermitOnly pour vous assurer que votre méthode et toutes les méthodes appelées ne disposent que d'un jeu d'autorisations restreintes. L'exemple ci-dessous applique un jeu d'autorisations très restreintes. Le code a seulement le droit de s'exécuter. Il ne peut pas accéder aux ressources, ni effectuer d'autres opérations privilégiées.
[SecurityPermissionAttribute(SecurityAction.PermitOnly,
Flags=SecurityPermissionFlag.Execution)]
public void SomeMethod()
{
// La méthode et le code en aval actuels n'ont qu'une autorisation d'exécution. Ils ne peuvent pas accéder aux
// ressources ni effectuer d'autres opérations privilégiées.
SomeOtherMethod();
} Les sections suivantes expliquent comment utiliser la sécurité d'accès au code pour restreindre les divers types d'accès aux ressources, y compris les E/S de fichier, le journal des événements, le Registre, les accès aux données, les services d'annuaire, les variables d'environnement, les services Web et les sockets.
E/S de fichier
Pour pouvoir effectuer une E/S de fichier, la stratégie de sécurité d'accès au code doit accorder à votre assembly l'autorisation FileIOPermission. Si votre code dispose de l'autorisation illimitée FileIOPermission, il peut accéder aux fichiers n'importe où dans le système de fichiers, auquel s'applique la sécurité Windows. Une autorisation restreinte FileIOPermission peut être utilisée pour limiter les capacités d'un assembly à effectuer des E/S de fichier, par exemple, en spécifiant les droits d'accès autorisés (lecture, lecture/écriture, etc.)
Restriction des E/S de fichier dans le contexte de votre application
Une condition commune consiste à pouvoir restreindre les E/S de fichier à des emplacements de répertoire spécifiques, telle que la hiérarchie de répertoires de votre application.
Remarque : si votre application Web est configurée pour une confiance moyenne, l'accès aux fichiers est automatiquement limité à la hiérarchie de répertoires virtuels de l'application. Pour plus d'informations, reportez-vous au module 9 « Utilisation de la sécurité d'accès au code avec ASP.NET ».
La configuration de votre application pour une confiance moyenne constitue un moyen de restreindre les E/S de fichier, bien qu'il limite également les capacités de votre application à accéder aux autres types de ressources. Il existe deux autres moyens qui permettent de restreindre les capacités d'E/S de fichier de votre code :
-
utiliser PermitOnly pour restreindre les E/S de fichier ;
-
configurer la stratégie de sécurité d'accès au code pour restreindre les E/S de fichier.
Utilisation de PermitOnly pour restreindre les E/S de fichier
Vous pouvez utiliser des attributs déclaratifs avec SecurityAction.PermitOnly pour restreindre les E/S de fichier comme le montre l'exemple suivant :
// Ne permettre au code que de lire les fichiers à partir de c:\VotreRépertApp
[FileIOPermission(SecurityAction.PermitOnly, Read=@"c:\VotreRépertApp\")]
[FileIOPermission(SecurityAction.PermitOnly, PathDiscovery=@"c:\VotreRépertApp\")]
public static string ReadFile(string filename)
{
// Utiliser Path.GetFilePath() pour canonicaliser le nom de fichier
// Utiliser FileStream.OpenRead pour ouvrir le fichier
// Utiliser FileStream.Read pour accéder aux données et les renvoyer
}
Remarque : le second attribut qui spécifie l'accès PathDicovery est requis par la fonction Path.GetFilePath utilisée pour constituer le nom de fichier d'entrée complet.
Pour éviter de pré-programmer la hiérarchie des répertoires de votre application, utilisez une syntaxe de sécurité impérative et HttpContext.Current.Request.MapPath(".") pour extraire le répertoire de votre application Web au moment de l'exécution. Vous devez référencer l'assembly System.Web et ajouter l'instruction using correspondante, comme le montre l'exemple suivant :
using System.Web;
public static string ReadFile(string filename)
{
string appDir = HttpContext.Current.Request.MapPath(".");
FileIOPermission f = new FileIOPermission(PermissionState.None);
f.SetPathList(FileIOPermissionAccess.Read, appDir);
f.SetPathList(FileIOPermissionAccess.PathDiscovery, appDir);
f.PermitOnly();
// Utiliser Path.GetFilePath() pour canonicaliser le nom de fichier
// Utiliser FileStream.OpenRead pour ouvrir le fichier
// Utiliser FileStream.Read pour accéder aux données et les renvoyer
}
Remarque : dans le cas d'une application Windows, vous pouvez remplacer l'appel à MapPath par un appel à Directory.GetCurrentDirectory afin d'obtenir le répertoire courant de l'application.
Configuration de la stratégie de sécurité d'accès au code pour restreindre les E/S de fichier
Un administrateur peut également configurer la stratégie de sécurité d'accès au code afin de restreindre les capacités du code à effectuer des E/S de fichier au-delà de la hiérarchie de répertoires virtuels de votre application.
Par exemple, l'administrateur peut configurer une stratégie de sécurité d'accès au code au niveau Entreprise ou Machine afin d'accorder une autorisation restreinte FileIOPermission à votre assembly. Ceci est particulièrement simple si votre assembly comporte un nom sûr du fait que l'administrateur peut utiliser cette preuve sûre au niveau cryptographique lors de la configuration de la stratégie. Pour les assemblys qui ne portent pas de nom sûr, une autre forme de preuve doit être utilisée. Pour plus d'informations sur la configuration de la sécurité d'accès au code afin de restreindre les capacités d'E/S de fichier d'un assembly, reportez-vous à la section « Procédure : configuration de la stratégie de sécurité d'accès au code pour limiter un assembly » de ce guide.
Si votre assembly est appelé par une application Web, une meilleure approche consiste à configurer la stratégie de sécurité d'accès au code ASP.NET (au niveau du domaine d'application) car vous pouvez utiliser $AppDirUrl$ qui représente le répertoire principal virtuel de l'application. Pour plus d'informations sur la restriction de E/S de fichier à l'aide de la stratégie de sécurité d'accès au code ASP.NET, reportez-vous au module 9, « Utilisation de la sécurité d'accès au code avec ASP.NET ».
Demande de FileIOPermission
En vue d'aider l'administrateur, si vous connaissez les conditions d'E/S de fichier requises et précises de votre assembly au moment de la génération (les noms des répertoires, par exemple), déclarez les conditions FileIOPermission de votre assembly à l'aide d'une demande d'autorisation déclarative comme le montre l'exemple suivant :
[assembly: FileIOPermission(SecurityAction.RequestMinimum, Read=@"C:\VotreRépertApp")]
L'administrateur peut voir cet attribut en utilisant permview.exe. L'avantage supplémentaire présenté par l'utilisation de SecurityAction.RequestMinimum est que l'assembly ne parvient pas à se charger s'il ne présente pas les autorisations suffisantes. Ceci est préférable à la génération d'une exception de sécurité d'exécution.
Journal des événements
Pour pouvoir accéder au journal des événements, la stratégie de sécurité d'accès au code doit accorder à votre assembly l'autorisation EventLogPermission. Dans le cas contraire, par exemple s'il s'exécute dans le contexte d'une application Web de confiance moyenne, vous devez mettre le code de consignation des événements en sandbox. Pour plus d'informations sur l'accès en sandbox au journal des événements, reportez-vous au module 9 « Utilisation de la sécurité d'accès au code avec ASP.NET ».
Restriction du code de consignation des événements
Si vous souhaitez restreindre les actions du code wrapper du journal des événements, un code peut-être écrit par un autre développeur ou une société de développement, utilisez des attributs déclaratifs avec SecurityAction.PermitOnly comme le montre l'exemple suivant.
L'attribut suivant garantit que la méthode WriteToLog et toutes les méthodes qu'il appelle ne peuvent accéder qu'au journal des événements de l'ordinateur local et ne peuvent pas supprimer de journaux d'événements, ni de sources d'événements. Ces opérations ne sont pas autorisées par EventLogPermissionAccess.Instrument.
[EventLogPermission(SecurityAction.PermitOnly,
MachineName=".",
PermissionAccess=EventLogPermissionAccess.Instrument)]
public static void WriteToLog( string message )
Pour renforcer l'accès en lecture uniquement, utilisez EventLogPermissionAccess.Browse.
Demande de EventLogPermission
Pour documenter les conditions d'autorisation requises pour votre code et veiller à ce que votre assembly ne se charge pas si la stratégie de sécurité d'accès au code lui accorde un accès au journal des événements insuffisant, ajoutez l'attribut EventLogPermissionAttribute au niveau assembly avec SecurityAction.RequestMinimum comme le montre l'exemple suivant :
// Cet attribut indique que votre code a besoin d'accéder aux
// journaux d'événements de la machine locale uniquement (".")
et a besoin d'un accès d'instrumentation,
// ce qui signifie qu'il peut lire ou écrire dans des journaux existants et créer de nouvelles sources d'événements
// et des journaux d'événements
[assembly: EventLogPermissionAttribute(SecurityAction.RequestMinimum,
MachineName=".",
PermissionAccess=
EventLogPermissionAccess.Instrument)] Registre
La stratégie de sécurité d'accès au code doit accorder l'autorisation RegistryPermission au code qui accède au Registre à l'aide de la classe Microsoft.Win32.Registry. Ce type d'autorisation peut être utilisé pour limiter l'accès au Registre à des clés et des sous-clés spécifiques et peut également contrôler les capacités du code à lire, écrire ou créer des clés de Registre et des valeurs nommées.
Restriction des accès au Registre
Pour limiter le code à lire les données de clés de Registre spécifiques, utilisez l'attribut RegistryPermissionAttribute avec SecurityAction.PermitOnly. L'attribut suivant garantit que le code ne peut être lu qu'à partir de la clé VotreApp (et les sous-clés) sous HKEY_LOCAL_MACHINE\SOFTWARE.
[RegistryPermissionAttribute(SecurityAction.PermitOnly,
Read=@"HKEY_LOCAL_MACHINE\SOFTWARE\VotreApp")]
public static string GetConfigurationData( string key, string namedValue )
{
return (string)Registry.
LocalMachine.
OpenSubKey(key).
GetValue(namedValue);
} Demande de RegistryPermission
Pour documenter les conditions d'autorisation requises pour votre code et veiller à ce que votre assembly ne se charge pas si la stratégie de sécurité d'accès au code lui accorde un accès au Registre insuffisant, ajoutez l'attribut RegistryPermissionAttribute au niveau assembly avec SecurityAction.RequestMinimum comme le montre l'exemple suivant :
[assembly: RegistryPermissionAttribute(SecurityAction.RequestMinimum,
Read=@"HKEY_LOCAL_MACHINE\SOFTWARE\VotreApp")] Accès aux données
Le fournisseur de données ADO.NET SQL Server prend en charge les appelants de confiance partielle. Les autres fournisseurs de données, y compris les fournisseurs de base de données OLE, Oracle et ODBC requièrent actuellement des appelants de confiance totale.
Si vous vous connectez à SQL Server via le fournisseur de données de SQL Server, votre code d'accès aux données requiert l'autorisation SqlClientPermission. Vous pouvez utiliser SqlClientPermission pour limiter la plage de paires nom/valeur possibles pouvant être utilisées sur une chaîne de connexion transmise à l'objet SqlConnection. Dans le code suivant, la méthode CheckProductStockLevel a été améliorée par un contrôle de sécurité supplémentaire afin de s'assurer que les mots de passe vides ne peuvent pas être utilisés dans la chaîne de connexion. Si le code extrait une chaîne de connexion avec un mot de passe vide, une exception SecurityException est lancée.
[SqlClientPermissionAttribute(SecurityAction.PermitOnly,
AllowBlankPassword=false)]
public static int CheckProductStockLevel(string productCode)
{
// Extraire la chaîne de connexion du Registre
string connectionString = GetConnectionString();
. . .
}
Pour plus d'informations sur la mise en sandbox du code d'accès au données pour permettre aux fournisseurs de base de données OLE et autres fournisseurs de données d'être utilisés à partir d'applications de confiance partielle, reportez-vous au module 9, « Utilisation de la sécurité d'accès au code avec ASP.NET ».
Services d'annuaire
Actuellement, le code qui utilise les classes de l'espace de noms System.DirectoryServices pour accéder aux services d'annuaire, tel que Active Directory doit être de confiance totale. Cependant, vous pouvez utiliser l'autorisation DirectoryServicesPermission pour limiter le type d'accès et les services d'annuaire auxquels le code peut se connecter.
Restriction des accès au service d'annuaire
Pour restreindre le code, utilisez l'attribut DirectoryServicesPermissionAttribute avec SecurityAction.PermitOnly. L'attribut suivant garantit que le code peut se connecter uniquement à un chemin d'accès LDAP spécifique et ne peut que parcourir l'annuaire.
[DirectoryServicesPermissionAttribute(SecurityAction.PermitOnly,
Path="LDAP://rootDSE",
PermissionAccess=DirectoryServicesPermissionAccess.Browse)]
public static string GetNamingContext(string ldapPath)
{
DirectorySearcher dsSearcher = new DirectorySearcher(ldapPath);
dsSearcher.PropertiesToLoad.Add("defaultNamingContext");
dsSearcher.Filter = "";
SearchResult result = dsSearcher.FindOne();
return (string)result.Properties["adsPath"][0];
} Demande de DirectoryServicesPermission
Pour documenter les conditions d'autorisation requises pour votre code et veiller à ce que votre assembly ne se charge pas si la stratégie de sécurité d'accès au code lui accorde un accès aux services d'annuaire insuffisant, ajoutez l'attribut DirectoryServicesPermissionAttribute au niveau assembly avec SecurityAction.RequestMinimum comme le montre l'exemple suivant :
[assembly: DirectoryServicesPermissionAttribute(SecurityAction.RequestMinimum,
Path="LDAP://rootDSE",
PermissionAccess=DirectoryServicesPermissionAccess.Browse)] Variables d'environnement
La stratégie de sécurité d'accès au code doit accorder l'autorisation EnvironmentPermission au code devant lire ou écrire des variables d'environnement à l'aide de la classe System.Environment. Ce type d'autorisation peut être utilisé pour limiter l'accès à des variables d'environnement nommées spécifiques.
Restriction des accès aux variables d'environnement
Pour restreindre le code de sorte qu'il ne lise uniquement des variables d'environnement spécifiques, utilisez l'attribut EnvironmentPermissionAttribute avec SecurityAction.PermitOnly. Les attributs suivants garantissent que le code ne peut être lu qu'à partir des variables nomutilisateur, domaineutilisateur et temp.
[EnvironmentPermissionAttribute(SecurityAction.PermitOnly, Read="nomutilisateur")]
[EnvironmentPermissionAttribute(SecurityAction.PermitOnly, Read="domaineutilisateur")]
[EnvironmentPermissionAttribute(SecurityAction.PermitOnly, Read="temp")]
public static string GetVariable(string name)
{
return Environment.GetEnvironmentVariable(name);
} Demande de EnvironmentPermission
Pour documenter les conditions d'autorisation requises pour votre code et veiller à ce que votre assembly ne se charge pas si la stratégie de sécurité d'accès au code lui accorde un accès aux variables d'environnement insuffisant, ajoutez l'attribut EnvironmentPermissionAttribute au niveau assembly avec SecurityAction.RequestMinimum comme le montre l'exemple suivant :
[assembly: EnvironmentPermissionAttribute(SecurityAction.RequestMinimum,
Read="nomutilisateur"),
EnvironmentPermissionAttribute(SecurityAction.RequestMinimum,
Read="domaineutilisateur"),
EnvironmentPermissionAttribute(SecurityAction.RequestMinimum,
Read="temp")] Services Web
La stratégie de sécurité d'accès au code doit accorder l'autorisation WebPermission au code qui appelle les services Web. En fait, l'autorisation WebPermission limite l'accès à toutes les ressources Internet HTTP.
Restriction des connexions aux services Web
Pour limiter les services Web auxquels votre code peut avoir accès, utilisez l'attribut WebPermissionAttribute avec SecurityAction.PermitOnly. Par exemple, le code suivant garantit que la méthode PlaceOrder et toutes les méthodes qu'il appelle ne peuvent invoquer que les services Web sur le site http://hôtequelconque.
[WebPermissionAttribute(SecurityAction.PermitOnly,
ConnectPattern=@"http://hôtequelconque/.*")]
[EnvironmentPermissionAttribute(SecurityAction.PermitOnly, Read="NOMUTILISATEUR")]
public static void PlaceOrder(XmlDocument order)
{
PurchaseService.Order svc = new PurchaseService.Order();
// Le service Web utilise l'authentification Windows
svc.Credentials = System.Net.CredentialCache.DefaultCredentials;
svc.PlaceOrder(order);
}
Dans l'exemple précédent, la propriété ConnectPattern de la classe WebPermissionAttribute est utilisée. Ceci permet de fournir une expression standard qui correspond à la plage d'adresses auxquelles une connexion peut être établie. L'attribut EnvironmentPermissionAttribute indiqué précédemment est requis car le code utilise l'authentification Windows et les informations d'identification par défaut.
L'exemple ci-dessous montre comment utiliser l'attribut Connect pour limiter les connexions à un service Web spécifique.
[WebPermissionAttribute(SecurityAction.PermitOnly,
Connect=@"http://hôtequelconque/order.asmx")] Sockets et DNS
La stratégie de sécurité d'accès au code doit accorder l'autorisation SocketPermission au code qui utilise des sockets directement à l'aide de la classe System.Net.Sockets.Socket. En outre, si votre code utilise DNS pour mapper les noms d'hôte sur les adresses IP, il requiert l'autorisation DnsPermission.
Pour limiter l'accès à des ports particuliers d'hôtes spécifiques, utilisez l'autorisation SocketPermission. Vous pouvez également restreindre l'utilisation du socket pour accepter des connexions ou initialiser les connexions sortantes et limiter le protocole de transport, TCP (Transmission Control Protocol) ou UDP (User Datagram Protocol) par exemple.
Restriction des accès aux sockets
Pour restreindre le code de sorte qu'il utilise les sockets de façon limitée uniquement, utilisez l'attribut SocketPermissionAttribute avec SecurityAction.PermitOnly. Les attributs suivants garantissent que le code peut se connecter uniquement à un port particulier sur un hôte spécifique à l'aide du protocole TCP. Comme le code appelle également Dns.Resolve pour résoudre un nom d'hôte, le code requiert également l'autorisation DnsPermission.
[SocketPermissionAttribute(SecurityAction.PermitOnly,
Access="Connect",
Host="hostname",
Port="80",
Transport="Tcp")]
[DnsPermissionAttribute(SecurityAction.PermitOnly, Unrestricted=true)]
public string MakeRequest(string hostname, string message)
{
Socket socket = null;
IPAddress serverAddress = null;
IPEndPoint serverEndPoint = null;
byte[] sendBytes = null, bytesReceived = null;
int bytesReceivedSize = -1, readSize = 4096;
serverAddress = Dns.Resolve(hostname).AddressList[0];
serverEndPoint = new IPEndPoint(serverAddress, 80);
socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
bytesReceived = new byte[readSize];
sendBytes = Encoding.ASCII.GetBytes(message);
socket.Connect(serverEndPoint);
socket.Send(sendBytes);
bytesReceivedSize = socket.Receive(bytesReceived, readSize, 0);
socket.Close();
if(-1 != bytesReceivedSize)
{
return Encoding.ASCII.GetString(bytesReceived, 0, bytesReceivedSize);
}
return "";
} Demande de SocketPermission et DnsPermission
Pour documenter les conditions d'autorisation requises pour votre code et veiller à ce que votre assembly ne se charge pas si la stratégie de sécurité d'accès au code lui accorde un accès aux sockets ou DNS insuffisant, ajoutez l'attribut SocketPermissionAttribute au niveau assembly avec SecurityAction.RequestMinimum comme le montre l'exemple suivant :
[assembly: SocketPermissionAttribute(SecurityAction.RequestMinimum,
Access="Connect",
Host="hostname",
Port="80",
Transport="Tcp")
DnsPermissionAttribute(SecurityAction.PermitOnly, Unrestricted=true)] Code non géré
Le code qui appelle des API Win32 ou des composants COM non gérés requiert l'autorisation de code non géré. Cette autorisation ne doit être accordée qu'à un code de très haute confiance. Elle est définie par le type SecurityPermission avec sa propriété Flags définie à SecurityPermissionFlag.UnmanagedCode.
Les directives suivantes permettant d'appeler un code non géré s'appuient sur celles présentées dans le module 7, « Création d'assemblys sécurisés ».
-
utiliser des conventions d'attribution des noms pour indiquer les risques ;
-
demander l'autorisation de code non géré ;
-
utiliser des appels d'API non gérée en sandbox ;
-
utiliser l'attribut SupressUnmanagedCodeSecurityAttribute avec précaution.
Utilisation des conventions d'attribution des noms pour indiquer les risques
Classifiez votre code non géré et ajoutez un préfixe aux types utilisés pour encapsuler les API non gérées à l'aide de la convention d'attribution des noms suivante.
-
Safe. Ceci identifie un code qui ne présente aucune menace de sécurité possible. Il n'y a pas de danger, quel que soit le code à appeler, malveillant ou autre. Il peut s'agir par exemple, du code qui renvoie le nombre de cycles courant du processeur. Des classes sûres (safe) peuvent être annotées avec l'attribut SuppressUnmanagedCode qui désactive la demande d'autorisation de sécurité d'accès au code de confiance totale.
[SuppressUnmanagedCode] class SafeNativeMethods { [DllImport("user32")] internal static extern void MessageBox(string text); } -
Native. Potentiellement, il peut s'agir d'un code non géré dangereux, mais c'est un code protégé par une demande de parcours complet de la pile pour l'autorisation de code non géré. Il est constitué de manière implicite par la couche d'interopérabilité à moins qu'il n'ait été supprimé par l'attribut SupressUnmanagedCode.
class NativeMethods { [DllImport("user32")] internal static extern void FormatDrive(string driveLetter); } -
Unsafe. Potentiellement, il s'agit d'un code non géré dangereux pour lequel la demande de sécurité d'autorisation de code non géré a été supprimée par déclaration. Ces méthodes présentent un danger potentiel. Tout appelant à ces méthodes doit effectuer une révision de sécurité complète pour s'assurer que leur utilisation est sûre et protégée car aucun parcours de pile n'est effectué.
[SuppressUnmanagedCodeSecurity] class UnsafeNativeMethods { [DllImport("user32")] internal static extern void CreateFile(string fileName); }
Demande d'autorisation de code non géré
Avec nom sûr
[assembly: SecurityPermission(SecurityAction.RequestMinimum,
UnmanagedCode=true)] Utilisation des appels d'API non gérée en sandbox
Isolez les appels de code non géré dans des assemblys spécifiques et conservez un nombre minimum d'assemblys appelant ce type de code. Ensuite, utilisez le schéma de sandbox pour garantir que l'autorisation de code non géré est accordée uniquement aux assemblys sélectionnés.
-
Pour mettre en sandbox votre code géré qui appelle un code non géré, procédez comme suit :
-
Placez votre code appelant un code non géré dans un assembly distinct (wrapper).
-
Ajoutez un nom sûr à l'assembly.
Ceci permet à la stratégie de sécurité d'accès au code personnalisé d'être appliquée facilement à l'assembly. Pour plus d'informations, reportez-vous à la section « Noms sûrs » du module 7 « Création d'assemblys sécurisés ». -
Demandez l'autorisation de code non géré (comme décrit à la section précédente).
-
Autorisez l'appel de code avec une demande d'autorisation complète.
Généralement, vous devez utiliser une autorisation personnalisée qui représente la ressource non gérée exposée par votre assembly. Par exemple :(new EncryptionPermission(EncryptionPermissionFlag.Encrypt, storePermissionFlag.Machine)).Demand(); -
Confirmez l'autorisation de code non géré dans votre classe wrapper :
(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert();
-
Pour un exemple d'implémentation complète indiquant comment appeler la fonctionnalité DPAPI Win32 non gérée, reportez-vous à la section « Procédure : création d'une autorisation de cryptage personnalisée » de ce guide.
Utilisation de l'attribut SupressUnmanagedCodeSecurityAttribute avec précaution
Si votre assembly effectue de nombreux appels à du code non géré, le traitement des performances associé aux multiples demandes d'autorisation de code non géré peut devenir un problème.
Dans ce cas, vous pouvez utiliser l'attribut SupressUnmanagedCodeSecurity sur la déclaration de la méthode P/Invoke. Ceci entraîne le remplacement de la demande complète d'autorisation non gérée par une demande de liaison qui ne se produit qu'une seule fois au moment de la compilation JIT.
Associé à l'utilisation de demandes de liaison, votre code est désormais vulnérable aux attaques par leurre. Afin de réduire les risques, il suffit de supprimer la demande d'autorisation de code non géré si votre assembly prend les précautions adéquates pour garantir qu'il ne peut pas être forcé par un code malveillant à effectuer des opérations non souhaitées. Un exemple de contre-mesure appropriée est lorsque votre assembly demande une autorisation personnalisée qui reflète plus précisément l'opération effectuée par le code non géré.
Utilisation de SuppressUnmanagedCodeSecurity avec la méthode P/Invoke
Le code suivant montre comment appliquer l'attribut SuppressUnmanagedCodeSecurity à une déclaration de méthode P/Invoke (Platform Invocation Services) :
public NativeMethods
{
// L'utilisation de SuppressUnmanagedCodeSecurity ici ne s'applique qu'à FormatMessage
[DllImport("kernel32.dll"), SuppressUnmanagedCodeSecurity]
private unsafe static extern int FormatMessage(
int dwFlags,
ref IntPtr lpSource,
int dwMessageId,
int dwLanguageId,
ref String lpBuffer, int nSize,
IntPtr *Arguments);
} Utilisation de SuppressUnmanagedCodeSecurity avec COM Interop
Pour les appels COM interop, l'attribut doit être utilisé au niveau de l'interface, comme le montre l'exemple suivant :
[SuppressUnmanagedCodeSecurity]
public interface IComInterface
{
} Délégués
Il n'y a aucun moyen de savoir par avance ce qu'une méthode déléguée va faire lorsque vous l'appelez. Si votre assembly prend en charge les appelants de confiance partielle, vous devez prendre des précautions supplémentaires lorsque vous appelez un délégué. Vous pouvez utiliser la sécurité d'accès au code pour renforcer davantage la sécurité :
-
envisager la restriction des autorisations pour le délégué ;
-
ne pas confirmer une autorisation avant l'appel d'un délégué.
Étude de la restriction des autorisations pour le délégué
Les autorisations accordées au code qui appelle le délégué déterminent les capacités de ce dernier. Si votre code dispose d'un nombre d'autorisations supérieur au code qui vous donne le délégué, ceci fournit un moyen à l'appelant d'exécuter un code à l'aide d'autorisations élevées. Pour résoudre ce problème, vous pouvez autoriser le code externe au point où il vous transmet le délégué à l'aide d'une demande d'autorisation appropriée ou vous pouvez restreindre les autorisations du délégué juste avant de l'appeler à l'aide d'un modificateur de pile Deny ou PermitOnly. Par exemple, le code ci-dessous n'accorde au code délégué qu'une autorisation d'exécution pour restreindre ses capacités.
// Définition de délégué public delegate void SomeDelegate(); . . . // Autoriser uniquement l'exécution avant d'appeler le délégué. Cela empêche le // code de délégué d'accéder aux ressources ou d'effectuer d'autres opérations // privilégiées new SecurityPermission(SecurityPermissionFlag.Execution).PermitOnly(); // Maintenant, appeler le délégué "limité" SomeDelegate(); // Rétablir le modificateur de pile d'autorisation seule CodeAccessPermission.RevertPermitOnly();
Non-confirmation d'une autorisation avant l'appel d'un délégué
L'assertion d'une autorisation avant l'appel d'un délégué est une opération dangereuse à réaliser du fait que vous n'avez aucune connaissance de la nature ou du niveau de confiance du code qui sera exécuté lorsque vous appelez le délégué. Le code qui vous transmet le délégué est sur la pile des appels et peut de ce fait être vérifié à l'aide d'une demande de sécurité appropriée. Cependant, il n'y a pas moyen de connaître le niveau de confiance ou les autorisations accordées au code délégué.
Pour plus d'instructions sur l'utilisation des délégués en toute sécurité, reportez-vous à la section « Délégués » du module 7 « Création d'assemblys sécurisés ».
Sérialisation
Le code prenant en charge la sérialisation doit disposer de l'autorisation SecurityPermission avec son
attribut Flag défini à SerializationFormatter. Si vous développez des classes qui prennent en charge la sérialisation et que votre code prend en charge des appelants de confiance partielle, vous devez envisager l'utilisation de demandes d'autorisation supplémentaires pour placer des restrictions sur lesquelles le code peut sérialiser l'état de votre objet.
Restriction de la sérialisation
Si vous créez une classe qui implémente l'interface ISerializable permettant à votre objet d'être sérialisé, vous pouvez ajouter une demande d'autorisation à votre implémentation ISerializable.GetObjectData pour autoriser le code qui tente de sérialiser votre objet. Ceci est particulièrement important si votre code prend en charge des appelants de confiance partielle.
Par exemple, le fragment de code ci-dessous utilise une demande StrongNameIdentityPermission pour garantir que seul le code signé avec une clé privée particulière correspondant à la clé publique dans la demande peut sérialiser l'état de votre objet.
[StrongNameIdentityPermission(SecurityAction.Demand,
PublicKey="00240000048...97e85d098615")]
public override void GetObjectData(SerializationInfo info,
StreamingContext context)
Pour plus d'instructions sur une sérialisation en toute sécurité, reportez-vous à la section « Sérialisation » du module 7 « Création d'assemblys sécurisés ».
Résumé
La sécurité d'accès au code permet de restreindre ce que le code peut faire, de définir quel code peut appeler le vôtre et d'identifier le code. Dans des environnements de confiance totale dans lesquels votre code et celui qui vous appelle disposent du jeu illimité de toutes les autorisations, la sécurité d'accès au code est de moindre importance.
Si votre code prend en charge des appelants de confiance partielle, les risques encourus pour la sécurité sont plus grands. Dans des scénarios de confiance partielle, la sécurité d'accès au code permet de réduire certains des risques supplémentaires et de restreindre le code privilégié.
Ressources supplémentaires
Pour plus d'informations, reportez-vous aux ressources suivantes :
-
« Security in .NET: The Security Infrastructure of the CLR Provides Evidence, Policy, Permissions, and Enforcement Services » par Don Box, Magazine MSDN, septembre 2002, à l'adresse : http://msdn.microsoft.com/msdnmag.
-
« Security in .NET: Enforce Code Access Rights with the Common Language Runtime » par Keith Brown, Magazine MSDN, février 2001, à l'adresse : http://msdn.microsoft.com/msdnmag.
-
.NET Framework Security par LaMacchia, Lange, Lyons, Martin et Price, publié par Addison Wesley.