Modifications de sécurité dans le .NET Framework 4

Deux modifications majeures ont été apportées à la sécurité dans le .NET Framework version 4. La stratégie de sécurité au niveau de l'ordinateur a été éliminée, bien que le système d'autorisations reste en place, et la transparence de sécurité est devenue le mécanisme de contrainte de mise en conformité par défaut. (Pour plus d'informations, consultez Code transparent de sécurité, niveau 2). En outre, certaines opérations d'autorisation qui présentait de possibles failles de sécurité ont été rendues obsolète.

Remarque importanteImportant

La sécurité d'accès du code (CAS) n'a pas été supprimée. La stratégie de sécurité a été supprimée de CAS, mais la preuve et les autorisations sont toujours en vigueur.Quelques autorisations ont été supprimées et la transparence a simplifié l'application de la sécurité.Pour obtenir une vue d'ensemble des modifications, consultez Résumé des modifications de la sécurité d'accès du code.

Vous devez être conscient des points clés suivants :

  • La transparence distingue le code qui s'exécute dans le cadre de l'application du code qui s'exécute dans le cadre de l'infrastructure. Elle a été introduite dans le .NET Framework version 2.0 et a été améliorée pour devenir le mécanisme de contrainte de mise en conformité de la sécurité d'accès du code. Contrairement à la stratégie de sécurité, les règles de transparence de niveau 2 sont mises en applications au moment de l'exécution, pas au moment du chargement de l'assembly. Ces règles sont toujours appliquées, même pour les assemblys exécutés avec une confiance totale par défaut. Toutefois, la transparence de niveau 2 n'affecte pas le code d'un niveau de confiance total qui n'est pas annoté, tel que les applications bureautiques. Les assemblys (notamment les assemblys de bureau) marqués avec le SecurityTransparentAttribute et qui appellent des méthodes marquées avec le SecurityCriticalAttribute reçoivent une MethodAccessException. Vous pouvez modifier ce comportement en appliquant SecurityRulesAttribute et en attribuant à la propriété SecurityRulesAttribute.RuleSet la valeur Level1. Toutefois, vous devez procéder à cette modification uniquement pour la compatibilité descendante. Vous devez marquer explicitement une application bureautique comme étant transparente de sécurité afin d'y appliquer des restrictions de transparence.

  • Le code qui appelle des API de stratégie de sécurité reçoit une NotSupportedException en plus des avertissements du compilateur au moment de l'exécution. La stratégie peut être réactivée à l'aide de l'élément de configuration <NetFx40_LegacySecurityPolicy>. Lorsque la stratégie est activée, la transparence de sécurité est toujours appliquée. La stratégie de sécurité est appliquée au moment du chargement de l'assembly et n'a aucun effet sur la transparence, qui est appliquée par le runtime.

  • Les autorisations de demandes obsolètes (RequestMinimum, RequestOptional et RequestRefuse) reçoivent des avertissements du compilateur et ne fonctionnent pas dans le .NET Framework 4, mais elles ne lèvent pas d'exception. Les demandes Deny lèvent une NotSupportedException au moment de l'exécution.

  • L'action de sécurité LinkDemand n'est pas obsolète, mais elle ne doit pas être utilisée pour la vérification des autorisations. À la place, utilisez le SecurityCriticalAttribute pour les types et méthodes qui nécessitent une confiance totale ou utilisez la méthode Demand pour les types et méthodes qui requièrent des autorisations individuelles.

  • Si votre application est générée avec Visual Studio 2010, vous pouvez l'exécuter sans ces modifications en spécifiant une version du .NET Framework cible antérieure au .NET Framework 4 dans les paramètres de projet Visual Studio. Toutefois, vous ne serez pas en mesure d'utiliser les nouveaux types et membres .NET Framework 4. Vous pouvez également spécifier une version antérieure du .NET Framework à l'aide de l'élément <supportedRuntime> du schéma de paramètres de démarrage de votre fichier de configuration d'application.

Les sections suivantes traitent de ces modifications et d'autres changements du .NET Framework 4 : 

  • Simplification de la stratégie de sécurité

  • Transparence de sécurité de niveau 2

  • Demandes d'autorisation obsolètes

  • APTCA conditionnel

  • Objets de preuve

  • Collections de preuves

Simplification de la stratégie de sécurité

À partir du .NET Framework 4, le Common Language Runtime (CLR) cesse de fournir des stratégies de sécurité pour les ordinateurs. Historiquement, le .NET Framework fournissait une stratégie de sécurité d'accès du code (CAS) sous la forme d'un mécanisme qui configurait et contrôlait étroitement les fonctionnalités du code managé. Bien que cette stratégie CAS soit puissante, elle peut s'avérer compliquée et restrictive. En outre, elle ne s'applique pas aux applications natives. Ses garanties de sécurité sont donc limitées. Les administrateurs système doivent se tourner vers les solutions au niveau du système d'exploitation telles que les stratégies de restriction logicielle Windows (SRP) ou AppLocker sous Windows 7 et Windows Server 2008 R2 pour remplacer la stratégie CAS. Les stratégies SRP et AppLocker fournissent des mécanismes d'approbation simples qui s'appliquent à la fois au code managé et au code natif. Dans le cadre de la stratégie de sécurité, SRP et AppLocker sont plus simples et offrent une meilleure garantie de sécurité que CAS.

Dans le .NET Framework 4, la stratégie de sécurité au niveau de l'ordinateur est désactivée par défaut. Les applications qui ne sont pas hébergées (c'est-à-dire les applications exécutées via l'Explorateur Windows ou à partir d'une invite de commandes) s'exécutent maintenant avec une confiance totale. Cela inclut toutes les applications qui résident sur des partages du réseau local. Les applications hébergées ou sandbox continuent à fonctionner avec les stratégies d'approbation décidées par leurs hôtes (par exemple, par Internet Explorer, ClickOnce ou ASP.NET). Les applications ou contrôles exécutés dans des bacs à sable (sandbox) sont considérés comme ayant un niveau de confiance partiel.

Pour simplifier la stratégie de sécurité, le modèle de transparence a été appliqué au .NET Framework. Les applications et contrôles exécutés dans un hôte ou un bac à sable (sandbox) avec le jeu d'autorisations limité accordé par le bac à sable sont considérés comme étant transparents. La transparence signifie que vous n'avez pas à vous préoccuper de la vérification de la stratégie CAS lorsque vous exécutez des applications avec un niveau de confiance partiel. Les applications transparentes sont simplement exécutées avec leur jeu d'autorisations. En tant que programmeur, votre seule préoccupation doit être que vos applications ciblent le jeu d'autorisations de leur bac à sable (sandbox) et qu'elles n'appellent pas du code nécessitant une confiance totale (code critique de sécurité).

Remarque importanteImportant

Suite à ces modifications de la stratégie de sécurité, il est possible que vous rencontriez des avertissements de compilation et des exceptions runtime si vous appelez des types et membres de stratégie CAS obsolètes explicitement ou implicitement (via d'autres types et membres).Pour obtenir la liste des types et membres obsolètes et de leurs remplaçants, consultez Compatibilité de la stratégie de sécurité d'accès du code et migration.

Vous pouvez éviter les avertissements et erreurs en utilisant l'élément de configuration <NetFx40_LegacySecurityPolicy> dans le schéma des paramètres du runtime pour opter pour le comportement de stratégie CAS hérité.Toutefois, la spécification de l'utilisation de la stratégie de sécurité héritée n'inclut pas d'éventuelles stratégies CAS personnalisées pour cette version à moins qu'elle ne soit migrée vers .NET Framework 4.

Vous pouvez également activer la stratégie CAS héritée en définissant la version du .NET Framework cible pour votre projet Visual Studio sur une version antérieure à .NET Framework 4. La stratégie CAS héritée est ainsi activée et comprend toutes les stratégies CAS personnalisées que vous avez spécifiées pour cette version.Toutefois, vous ne serez pas en mesure d'utiliser les nouveaux types et membres .NET Framework 4.Vous pouvez également spécifier une version antérieure du .NET Framework en utilisant l'élément <supportedRuntime> dans le schéma de paramètres de démarrage.

Retour au début

Transparence de sécurité de niveau 2

La transparence de sécurité a été introduite dans le .NET Framework version 2.0, mais elle était très limitée et principalement utilisée pour améliorer l'efficacité de la validation du code. Dans le .NET Framework 4, la transparence est un mécanisme de contrainte de mise en conformité qui distingue le code qui s'exécute dans le cadre de l'application du code qui s'exécute dans le cadre de l'infrastructure. La transparence établit un cloisonnement entre le code qui peut réaliser des actions privilégiées (code critique), notamment appeler le code natif, et le code qui ne le peut pas (code transparent). Le code transparent peut exécuter des commandes dans les limites de son jeu d'autorisations, mais il ne peut pas exécuter, appeler, dériver de ou contenir de code critique.

L'objectif principal de la contrainte de mise en conformité de transparence est de fournir un mécanisme simple et efficace pour isoler différents groupes de code en fonction de privilèges. Dans le modèle de bac à sable (sandbox), ces groupes de privilèges ont un niveau de confiance totale (autrement dit, non restreint) ou de confiance partielle (autrement dit, limité au jeu d'autorisations accordé au bac à sable).

Les applications bureautiques sont exécutées avec un niveau de confiance totale. Par conséquent, elles ne sont pas affectées par le modèle de transparence. Pour plus d'informations sur les modifications apportées à la transparence de sécurité, consultez Code transparent de sécurité, niveau 2.

Retour au début

Demandes d'autorisation obsolètes

La prise en charge du runtime a été supprimée afin d'appliquer les demandes d'autorisation Deny, RequestMinimum, RequestOptional et RequestRefuse. En général, ces demandes n'étaient pas bien comprises et présentaient de possibles failles de sécurité lorsqu'elles n'étaient pas correctement utilisées :

  • Une action Deny pouvait facilement être substituée par une action Assert. Le code d'un assembly pouvait exécuter une action Assert pour une autorisation si cette autorisation figurait dans le jeu d'autorisations de l'assembly. Le Assert empêchait le Deny d'être vu sur la pile, ce qui le rendait inopérant.

  • RequestMinimum ne pouvait pas être utilisé efficacement à l'extérieur de la portée de l'application. Si RequestMinimum figurait sur un fichier exécutable (.exe) et que le jeu d'autorisations n'était pas trouvé, les utilisateurs finaux du fichier recevaient une exception FileLoadException non gérée qui ne contenait pas d'informations à propos de la résolution du problème. Vous ne pouviez pas utiliser un jeu de demandes minimum unique pour les bibliothèques (fichiers .dll), car les différents types et membres de l'assembly ont généralement des besoins d'autorisation différents.

  • RequestOptional portait à confusion et était souvent utilisé de façon incorrecte, ce qui engendrait des résultats inattendus. Les développeurs pouvaient facilement omettre des autorisations dans la liste sans se rendre compte que, ce faisant, ils refusaient implicitement ces autorisations.

  • RequestRefuse ne fournissait pas un modèle de privilèges minimum efficace, car il exigeait que vous identifiiez explicitement les autorisations que vous ne souhaitiez pas au lieu d'identifier les autorisations dont vous aviez besoin. De plus, si de nouvelles autorisations devenaient disponibles, elles n'étaient pas incluses dans la liste. En outre, le refus n'était pas significatif pour toutes les autorisations. Par exemple, vous pouviez refuser une valeur pour la propriété UserQuota dans la IsolatedStoragePermission.

    Pour finir, le fait de spécifier uniquement les autorisations que vous ne souhaitiez pas engendrait de possibles failles de sécurité si vous ne parveniez pas à identifier toutes les autorisations potentiellement nuisibles.

  • RequestOptional et RequestRefuse permettaient aux développeurs de diviser des domaines homogènes en créant plusieurs jeux d'autorisations dans un domaine.

Le .NET Framework 4 supprime la contrainte de mise en conformité d'exécution de ces valeurs d'énumération. Les assemblys contenant les attributs qui utilisent ces valeurs SecurityAction continueront de se charger. Toutefois, le CLR ne refusera pas de charger les assemblys référencés ou de modifier leur jeu d'autorisations en fonction des jeux d'autorisations.

Retour au début

APTCA conditionnel

L'utilisation conditionnelle de l'attribut AllowPartiallyTrustedCallersAttribute (APTCA) permet aux hôtes d'identifier les assemblys qu'ils souhaitent présenter aux appelants partiellement fiables chargés dans le contexte de l'hôte. Les assemblys candidats doivent déjà être conçus pour la confiance partielle, c'est-à-dire qu'ils doivent être APTCA (critiques sécurisés dans le modèle de transparence) ou complètement transparents. Un nouveau constructeur de AllowPartiallyTrustedCallersAttribute permet à l'hôte de spécifier le niveau de visibilité d'un assembly APTCA en utilisant l'énumération PartialTrustVisibilityLevel dans l'appel de constructeur.

Retour au début

Objets de preuve

Avant le .NET Framework 4, pratiquement tous les objets pouvaient être utilisés comme objets de preuve si le code d'hébergement souhaitait les appliquer comme preuve. Par exemple, certains extraits de code .NET Framework reconnaissaient les objets System.Uri en tant que preuve. Le runtime considérait les objets de preuve en tant que références System.Object et ne leur appliquait pas de sécurité de type.

Cela posait problème car le .NET Framework imposait des restrictions implicites sur les types qui pouvaient être utilisés comme objets de preuve. Plus précisément, tout objet utilisé comme preuve devait être sérialisable et ne pouvait pas être null. Si ces spécifications n'étaient pas satisfaites, le CLR levait une exception chaque fois qu'une opération qui nécessitait l'une de ces hypothèses était exécutée.

Pour activer des contraintes sur les types d'objets pouvant être utilisés comme preuve et pour fournir la capacité d'ajouter de nouvelles fonctionnalités et spécifications à tous les objets de preuve, le .NET Framework 4 présente une nouvelle classe de base, System.Security.Policy.EvidenceBase, à partir de laquelle tous les objets de preuve doivent dériver. La classe EvidenceBase vérifie, à l'instanciation, que l'objet de preuve est sérialisable. De plus, de nouvelles spécifications de preuve peuvent être créées ultérieurement en ajoutant de nouvelles implémentations par défaut à la classe de base.

Compatibilité descendante

Tous les types utilisés par le CLR en tant qu'objets de preuve ont été mis à jour dans le .NET Framework 4 de façon à dériver de EvidenceBase. Cependant, les types de preuve personnalisés de preuve utilisés par les applications tierces ne sont pas connus et ne peuvent pas être mis à jour. Par conséquent, ces types de preuve ne peuvent pas être utilisés avec les nouveaux membres qui s'attendent à ce que les preuves dérivent de EvidenceBase.

Retour au début

Collections de preuves

Avant le .NET Framework 4, le CLR générait le jeu complet d'objets de preuve qui s'appliquait à un assembly lors de son chargement. Ces objets étaient stockés dans une liste, au sein de laquelle les consommateurs itéreraient ensuite pour rechercher un objet spécifique. Par conséquent, toutes les preuves étaient disponibles, qu'elles soient utilisées ou non. Pour la plupart des objets de preuve, ce comportement ne posait pas de problème. Cependant, pour les objets de preuve tels que System.Security.Policy.Publisher(qui requiert la vérification Authenticode), il pouvait s'avérer inefficace.

Pour améliorer ce comportement, l'interaction avec la collection de preuves a été reconçue dans le .NET Framework 4. Une collection de preuves se comporte maintenant comme un dictionnaire au lieu d'une liste. Au lieu d'itérer au sein de la collection de preuves pour voir si un objet de preuve requis existe, les consommateurs peuvent maintenant demander un type spécifique de preuve, et la collection retourne cette preuve si elle est trouvée. Par exemple, l'appel StrongName name = evidence.GetHostEvidence<StrongName>(); retourne un objet StrongName, s'il existe ; sinon, il retourne null.

Ce modèle de dictionnaire repousse la génération des objets de preuve jusqu'à ce qu'ils soient demandés. Dans l'exemple de preuve Publisher, la surcharge des performances liées à la vérification de la signature Authenticode d'un assembly est différée jusqu'à ce que ces informations soient demandées. Dans le cas le plus courant des applications de confiance totale où la preuve Publisher n'est pas exigée, le processus de vérification est entièrement évité.

Retour au début

Voir aussi

Concepts

Code transparent de sécurité (security-transparent)

Code transparent de sécurité, niveau 2

Compatibilité de la stratégie de sécurité d'accès du code et migration