Developpez.com - Microsoft DotNET
X

Choisissez d'abord la catégorieensuite la rubrique :

La sécurité dans Microsoft .NET Framework

Analyse par Foundstone, Inc. et CORE Security Technologies

Sommaire:

1. Introduction

2. Étendue et objectifs

3. Contexte : le problème de la sécurité des applications

4. Une solution : une architecture capable de gérer le risque logiciel
  4.1 Common Language Runtime
  4.2 Bibliothèques de classes
  4.3 Assemblys

5. Sécurité du .NET Framework en détail
  5.1 Sécurité basée sur les preuves
  5.2 Sécurité d'accès au code
  5.3 Processus de vérification
  5.4 Sécurité basée sur les rôles
  5.5 Cryptographie
  5.6 Domaines d'application

6. Conclusion
  6.1 Une conception et une administration insuffisantes compromettent encore la sécurité
  6.2 La sécurité est essentielle, à tous les niveaux

7. Ressources supplémentaires

Ce livre blanc présente une vue d'ensemble de l'architecture de la sécurité dans Microsoft .NET Framework. Il est fondé sur une analyse à long terme menée de manière indépendante par Foundstone, Inc. et CORE Security Technologies à partir de l'été 2000.

Notre analyse révèle que le .NET Framework, s'il est utilisé de manière appropriée, permet aux développeurs et aux administrateurs d'exercer un contrôle de sécurité granulaire sur leurs applications et leurs ressources ; il fournit aux développeurs un ensemble d'outils faciles à utiliser pour implémenter des routines d'authentification, d'autorisation et de cryptographie puissantes ; il élimine la plupart des risques majeurs de sécurité auxquels sont confrontées les applications actuelles en raison de code inadapté (notamment les dépassements de mémoire tampon) ; enfin, il transfère les tâches fastidieuses et critiques que sont les décisions de sécurité (par exemple, s'il faut exécuter ou non une application particulière ou bien si une application peut accéder ou non à une ressource donnée) des utilisateurs finals aux développeurs et aux administrateurs.

Dans ce document, nous allons décrire la manière dont les fonctionnalités de la sécurité basée sur les rôles et sur les preuves, la sécurité d'accès au code, le processus de vérification, la prise en charge de la cryptographie, le stockage isolé et les domaines d'application du .NET Framework interagissent pour obtenir ces résultats et offrir une plate-forme fiable permettant de développer et d'exécuter tous les types d'applications logicielles, à la fois côté client et côté serveur. Nous conclurons en constatant que le .NET Framework peut aider les organisations à mieux protéger leurs applications contre les attaques de sécurité présentes et futures.

1. Introduction


Dès les phases de développement initiales, Foundstone, Inc. et CORE Security Technologies ont apporté leur soutien à Microsoft en analysant et en évaluant la sécurité de l'architecture et de l'implémentation du .NET Framework.

Nous avons commencé à analyser le .NET Framework au cours de l'été 2000, avant la parution de la première version bêta du logiciel, et avons continué jusqu'à la version bêta 2. Notre participation a totalisé plus de 2 800 heures de travail, pendant lesquelles une équipe de dix experts a conduit de manière rigoureuse et indépendante des audits et des tests de sécurité. L'équipe, bénéficiant d'un accès total au code source et aux ingénieurs Microsoft, a pu se familiariser totalement avec l'architecture de sécurité du .NET Framework, des principes de conception à l'implémentation du code.

L'audit a été réalisé conformément aux méthodologies standard développées par Foundstone, Inc. et CORE Security Technologies. Celles-ci sont le fruit de nombreuses années d'expérience dans le domaine du test, de l'évaluation et de la sécurisation d'applications logicielles complexes pour des organisations diverses, qu'il s'agisse de nouvelles entreprises à des sociétés classées au Fortune 500. Du fait de notre position en tant que fournisseurs de solutions de sécurité, nous aimons à dire que nous avons tout vu, " le bon comme le mauvais ". Au cours de cette année passée à examiner les plus petits détails du .NET Framework, le travail collectif accompli a mis le .NET Framework à rude épreuve !

Ce livre blanc traite principalement des fonctionnalités de sécurité étendues du .NET Framework. Il s'appuie largement sur les résultats de l'évaluation que nous avons effectuée au cours de l'année dernière et de notre interaction continue avec l'équipe de développement du .NET Framework. Les réflexions et les opinions exprimées dans ce livre blanc sont strictement indépendantes et fondées sur des analyses et des tests rigoureux de nombreuses versions intermédiaires du logiciel. Nous espérons que ce document vous permettra de mieux comprendre les concepts de sécurité dans le .NET Framework et saura vous transmettre la confiance que nous avons dans cette architecture et son implémentation.

2. Étendue et objectifs


Dans ce document, nous allons examiner quelques-uns des problèmes de sécurité auxquels se heurtent fréquemment les entreprises lors des phases de conception et de développement de solutions logicielles. Nous examinerons ensuite les solutions qu'offre le .NET Framework par le biais de son architecture de sécurité.

En toute circonstance, notre objectif est d'expliquer de façon simple aux lecteurs possédant des connaissances techniques moyennes les concepts complexes de la sécurité du .NET Framework. Nous supposons que les lecteurs sont familiarisés avec les concepts fondamentaux du .NET Framework et nous ne présenterons pas en détail les technologies de base impliquées. De nombreuses références sont indiquées à la fin de ce document pour les personnes souhaitant obtenir des informations techniques plus complètes sur le .NET Framework.

3. Contexte : le problème de la sécurité des applications


Personne ne conteste aujourd'hui le fait que de nombreuses applications logicielles soient essentielles, en particulier celles qui reposent sur des technologies Internet. De simples canaux de manipulation de données statiques au départ, elles sont devenues des éléments de base complexes, dynamiques et orientés transactions du commerce d'entreprise.

Le niveau de complexité et de fonctionnalité toujours plus élevé des applications logicielles actuelles a cependant engendré un effet pervers inquiétant : un nombre croissant d'organisations voient leurs logiciels être victimes d'attaques de la part d'intrus internes et externes.

4. Une solution : une architecture capable de gérer le risque logiciel


L'architecture de code managé du .NET Framework fournit une solution décisive au problème de sécurité des applications logicielles. Elle contrôle en toute transparence le comportement du code même dans les circonstances les plus défavorables, réduisant considérablement les risques inhérents à tous les types d'applications (côté client et côté serveur). Utilisée de manière adéquate, il s'agit de l'une des meilleures plates-formes pour développer des applications Web d'entreprise répondant à des critères de sécurité stricts.

À un niveau élevé, le .NET Framework permet aux développeurs et aux administrateurs d'exercer un contrôle de sécurité granulaire sur leurs applications et leurs ressources ; il fournit aux développeurs un ensemble d'outils faciles à utiliser pour implémenter des routines d'authentification, d'autorisation et de cryptographie puissantes ; il élimine la plupart des risques majeurs de sécurité auxquels sont confrontées les applications actuelles en raison de code inadapté (notamment les dépassements de mémoire tampon) ; enfin, il transfère les tâches fastidieuses et critiques que sont les décisions de sécurité (par exemple, s'il faut exécuter ou non une application particulière ou bien si une application peut accéder ou non à une ressource donnée) des utilisateurs finals aux développeurs et aux administrateurs.

Le paradigme du code managé

Avant de traiter en détail la manière dont le .NET Framework obtient ces résultats, examinons les composants fondamentaux du .NET Framework, notamment :
  • le Common Language Runtime
  • les bibliothèques de classes
  • les assemblys.

    Common Language Runtime

    Le Common Language Runtime (CLR) est le moteur qui exécute et " gère " le code d'exécution. Du point de vue de la sécurité, le CLR met en oeuvre les restrictions d'exécution du code du .NET Framework et empêche celui-ci de se comporter de manière inattendue.

    Plus spécifiquement, le CLR effectue une compilation juste-à-temps (JIT, Just-In-Time) lors de l'exécution du code managé. Le compilateur JIT traduit le code managé en code natif avant de l'exécuter. Étant donné que le JIT génère le code au sein du CLR, ce dernier est positionné de manière unique pour en assurer la sécurité, un résultat qui ne peut pas être obtenu avec du code exécuté sans être traité dans l'environnement natif.

    Bibliothèques de classes

    Les bibliothèques de classes .NET Framework sont une collection de classes réutilisables, ou types, à disposition des développeurs pour écrire des programmes qui s'exécuteront dans le CLR. Elles implémentent de nombreuses fonctionnalités de sécurité importantes, parmi lesquelles les autorisations (c'est-à-dire le droit d'accéder à une ou plusieurs ressources système), les mécanismes d'authentification ainsi que les protocoles et primitives de cryptographie. La majeure partie des applications peut tirer profit de ces fonctionnalités de sécurité en utilisant simplement ces bibliothèques de classes (celles-ci ne requièrent pas de code spécifique à la sécurité). Nous couvrirons ces fonctionnalités plus en détail plus loin dans ce document.

    Assemblys

    Un assembly est un fichier exécutable ou une DLL compilé à l'aide de l'un des nombreux compilateurs de langage du .NET Framework. Les assemblys du .NET Framework peuvent être écrits dans les principaux langages de programmation, notamment Visual Basic, C#, C++, J#, Perl et COBOL, pour n'en citer que quelques-uns. Les développeurs peuvent ainsi bénéficier de la même infrastructure de sécurité tout en programmant dans le langage approprié à la tâche qu'ils accomplissent et à leur niveau de compétences.

    Les assemblys contiennent le code exécuté par le runtime au format MSIL (Microsoft Intermediate Language). Nous avons précédemment parlé de la manière dont le CLR compile juste-à-temps le code MSIL en code natif, ce qui permet d'appliquer stratégiquement la sécurité au code d'exécution. Les assemblys contiennent également des métadonnées dont se sert le CLR pour rechercher et charger des classes, disposer des instances en mémoire, résoudre des appels de méthodes, générer le code natif, mettre en oeuvre la sécurité et définir les limites du contexte du runtime.

    Grâce aux assemblys, le CLR et les bibliothèques de classes implémentent l'architecture de code managé du .NET Framework. Le reste de ce document traite de cette architecture plus en détail.

    5. Sécurité du .NET Framework en détail


    L'architecture de la sécurité du .NET Framework se compose de plusieurs éléments fondamentaux, notamment :
  • la sécurité basée sur les preuves
  • la sécurité d'accès au code
  • le processus de vérification
  • la sécurité basée sur les rôles
  • la cryptographie
  • les domaines d'application.

    Chaque élément est présenté en détail ci-après.

    Sécurité basée sur les preuves

    Les éléments clés du sous-système de la sécurité basée sur les preuves du .NET Framework incluent la stratégie, les autorisations et la preuve.

    Stratégie

    Toute personne familière avec la sécurité des systèmes informatiques vous dira qu'il est impossible de mettre en oeuvre une sécurité dans le vide et qu'elle doit être pilotée par une stratégie. Toute la sécurité du .NET Framework repose donc sur une stratégie XML définie avec minutie. La stratégie .NET Framework définit essentiellement les ressources qui sont accessibles par le code dans les assemblys d'exécution, empêchant ainsi le logiciel de nuire de manière errante ou malveillante à l'intégrité des données. La stratégie dans le .NET Framework est omniprésente et bien protégée contre tout accès par les utilisateurs qui ne sont pas administrateurs. Elle est installée automatiquement sur chaque ordinateur, pour chaque compte d'utilisateur, et peut être déployée facultativement sur des domaines Windows via une stratégie de groupe.

    La fonction de base de la stratégie de sécurité dans le .NET Framework consiste à associer les autorisations aux preuves (nous présenterons ces deux concepts dans un instant). La stratégie de sécurité par défaut fournie avec le .NET Framework a été conçue par Microsoft et vise à créer un environnement d'exécution sécurisé pour un utilisateur final standard. Elle peut aussi être personnalisée par des comptes administratifs disposant des droits d'accès appropriés, afin de répondre à des besoins spécifiques.

    Autorisations

    Les autorisations sont à la base de la stratégie. Elles décrivent une ou plusieurs ressources et les droits associés, et implémentent des méthodes de demande et d'assertion d'accès. Le .NET Framework inclut des autorisations pour les objets suivants : DataAccess, DNS, DirectoryServices, FileIO, EventLog, Environment, FileDialog, Registry, Reflection, Socket, Web, IsolatedStorage, UI, Printing, MessageQueue et Security. Les membres de ces objets incluent AllFlags, Assertion, ControlAppDomain, ControlDomainPolicy, ControlEvidence, ControlPolicy, ControlPrincipal, ControlThread, Execution, Infrastructure, NoFlags, RemotingConfiguration, SkipVerification et UnmanagedCode. Le développeur peut étendre les définitions de ces autorisations afin d'inclure les ressources définies par l'application et les méthodes de vérification des droits d'accès. De telles personnalisations granulaires ne peuvent pas être effectuées aussi facilement dans d'autres architectures de code managé telles que Java 2.

    Les développeurs peuvent contrôler la manière dont leur code réagit aux autorisations accordées par la stratégie en incorporant des demandes d'autorisation dans les assemblys. On distingue trois types de demandes d'autorisation : Minimal, Optional et Refuse. Si la stratégie n'accorde pas à un assembly tout ce qui est répertorié dans l'ensemble " Minimal ", l'assembly ne sera ni chargé ni exécuté. Les développeurs peuvent utiliser la demande " Refuse " pour décliner explicitement l'accès à des ressources auxquelles l'application a normalement accès mais qui ne sont pas nécessaires à son exécution. Cela signifie que les développeurs peuvent limiter l'étendue de l'ensemble des autorisations de leur application au-delà de ce que pourraient autoriser les stratégies définies par l'administrateur. Dans la mesure où le code peut refuser des autorisations, il n'est pas impliqué dans les problèmes de sécurité qui peuvent survenir avec ces mêmes autorisations. Il s'agit là d'une approche très granulaire comparée aux autres architectures de code managé telles que Java 2. Cela permet au code d'être conçu pour s'exécuter avec moins de privilèges.

    Stockage isolé

    Parmi toutes les autorisations couvertes par la sécurité basée sur les preuves, l'autorisation de stockage isolé vaut d'être mentionnée. Celle-ci offre un mécanisme de stockage de fichiers spécial reposant sur le système de fichiers sous-jacent, et assure que les différents référentiels de l'application restent isolés les uns par rapport aux autres et que les caractéristiques propres au système de fichiers ne sont pas révélées (telles que les noms des chemins d'accès, les lecteurs disponibles, etc.). En utilisant le stockage isolé, les assemblys de niveau de confiance partiel qui ne bénéficient pas de l'autorisation FileIO peuvent toujours recevoir l'autorisation de stocker localement des données spécifiques à l'application. Grâce à l'isolation stricte et à l'accessibilité limitée de ces zones de stockage, le système de fichiers ou l'ordinateur local est sécurisé. Cela est particulièrement utile pour exécuter du code de niveau de confiance partiel (par exemple, les applications Internet) tout en accordant la fonctionnalité puissante des capacités de stockage locales.

    Preuve

    Au moment de l'exécution, le CLR détermine les autorisations qui peuvent être assignées à un assembly particulier en évaluant la preuve de cet assembly. La preuve peut provenir d'une variété de sources résidant dans un assembly ou être obtenue à partir de l'environnement d'exécution local.

    Parmi les sources de preuve, on peut citer :
  • les espaces de noms scellés de manière cryptographique (noms forts) ;
  • l'identité de l'éditeur du logiciel (Authenticode®) ;
  • le code d'origine (adresse URL, site, Internet Explorer Zone).

    Intégration de la stratégie, des autorisations et de la preuve

    Jusqu'à présent, nous avons décrit séparément chacun des principaux composants du modèle de sécurité basée sur les preuves du .NET Framework. Toutefois, il est important de noter que ces composants interagissent parfaitement pour fournir un environnement d'exécution très différent de ceux auxquels nous sommes habitués lors de l'exécution de fichiers exécutables. Avec le .NET Framework, peu de décisions de sécurité doivent être prises par l'utilisateur au moment de l'exécution. Le .NET Framework s'assure déjà en toute transparence que le code exécuté par les utilisateurs finals met en oeuvre les principes de conception pour la sécurité de l'application, et ce à l'avance, dispensant l'utilisateur final de devoir prendre, sans être probablement la personne la mieux placée, des décisions importantes en matière de sécurité.

    Du point de vue du développeur, la majeure partie du travail s'effectue en arrière-plan. Tant que des autorisations suffisantes1 et des stratégies correctement configurées couvrent toutes les ressources impliquées, et tant que le développeur utilise du code managé pour y accéder, le contrôle des preuves et la mise en oeuvre de la stratégie requis sont traités en toute transparence.

    Sécurité d'accès au code

    La sécurité d'accès au code (CAS, Code Access Security) est le moteur qui s'assure que le code des assemblys n'excède pas les autorisations accordées au cours de l'exécution sur un système informatique. Lorsque les assemblys en code managé sont chargés pour exécution, ils sont associés à un ensemble correspondant d'autorisations. Si une méthode dans un assembly a besoin d'une autorisation pour accéder à une ressource, le code fournissant l'accès à cette ressource demandera l'objet d'autorisation approprié. Lorsque cela se produit, un parcours de la pile est initié. Ce processus contrôle que chaque assembly dans la chaîne d'appels a reçu l'autorisation demandée (pas seulement l'appelant immédiat). Si l'un des appelants échoue à ce test, une exception de sécurité est générée et l'opération demandée n'est pas accomplie. Le parcours de la pile empêche les " attaques piège ", où du code qui n'est pas digne de confiance tente de " piéger " le code d'un autre assembly, doté de droits d'accès plus larges, en vue d'appeler un objet protégé et de contourner les restrictions de sécurité.

    Lorsque vous utilisez les bibliothèques de classes .NET Framework sur des ressources pour lesquelles des stratégies et des autorisations ont déjà été définies, ce travail est effectué en arrière-plan. Les développeurs peuvent forcer la mise en oeuvre des contrôles des autorisations à l'aide de deux mécanismes : les contrôles impératifs et les contrôles déclaratifs. Les contrôles impératifs sont simplement des appels de méthode d'exécution au moteur de sécurité de base pour effectuer une demande ou ignorer des étapes de l'opération de parcours de la pile. Les contrôles de sécurité déclaratifs sont essentiellement les mêmes. Ils sont toutefois exprimés sous la forme d'attributs personnalisés qui sont évalués au moment de la compilation et incorporés dans des métadonnées. Les contrôles déclaratifs couvrent les mêmes opérations que les contrôles impératifs mais effectuent quelques contrôles supplémentaires qui sont implémentés uniquement au moment de la compilation JIT.

    Dans certaines circonstances, le code peut avoir besoin d'appeler la méthode d'assertion d'une autorisation afin de limiter les parcours de pile suivants au frame de pile de ce code. Cela lui permettra d'accéder à certaines ressources même lorsque les appelants de la méthode ne disposent pas des autorisations appropriées. Par exemple, le code fournissant l'accès aux fichiers demandera généralement à ses appelants de disposer de l'autorisation FileIO puis procédera à l'assertion de l'autorisation UnmanagedCode pour accéder au système de fichiers Windows sous-jacent. Cette technique doit être employée avec modération et n'est disponible que pour du code de niveau de confiance élevé et disposant de l'autorisation Assertion. Notez que l'opération d'assertion est précise et ne s'applique qu'à l'autorisation confirmée.

    La sécurité d'accès au code place donc la barre très haut pour tout intrus tentant d'abuser du comportement du code en cours d'exécution.

    Processus de vérification

    Une étape finale permet de garantir la sécurisation de l'exécution du code managé. Il s'agit du processus de vérification. Au cours de la compilation JIT, le CLR vérifie tout le code managé pour garantir la sécurité du type de mémoire. Ce processus élimine le risque de voir le code exécuter ou provoquer des actions " inattendues " qui pourraient contourner le flux de l'application commun et les contrôles de sécurité.

    Le processus de vérification permet d'éviter que des erreurs courantes ne se produisent, par exemple l'utilisation d'un entier comme pointeur pour accéder à des emplacements de mémoire arbitraires, le traitement d'un objet en tant que type différent pour autoriser la lecture d'un état privé ou de la mémoire hors des limites de l'objet, l'accès à un champ privé ou à une méthode en dehors de sa classe, ou encore l'accès à un objet nouvellement créé avant qu'il n'ait été initialisé pour provoquer une opération incorrecte ou accéder à des informations résiduelles en mémoire. D'autres erreurs, telles que le dépassement de mémoire tampon (c'est-à-dire fournir des paramètres qui excèdent la capacité attendue par la méthode appelée), la référence à une mémoire dont le contenu est autre que des variables définies ou des points d'entrée de méthode, la référence à des emplacements de pile hors du frame de pile alloué (références non valides) et le transfert de l'exécution à des emplacements arbitraires au sein d'un processus, sont aussi évitées grâce au processus de vérification. Cet ensemble d'erreurs courantes de programmation, qui sous-tend la majorité des faiblesses actuellement rencontrées en matière de sécurité, ne constitue plus une menace au sein de l'environnement de type sécurisé et managé fourni par le .NET Framework. Il s'agit sans doute là de l'un des avantages les plus intéressants de la conception d'applications à l'aide du .NET Framework.

    Note sur le code non managé

    On appelle code " non managé " le code exécuté à l'extérieur du champ de contrôle du CLR. Par définition, le code non managé n'est pas soumis aux mesures de sécurité du CLR et peut donc obtenir l'accès sans autorisation à des ressources dans l'environnement natif par l'intermédiaire d'attaques traditionnelles.

    Heureusement, la plupart des applications n'auront jamais besoin d'appeler directement le code natif. Les bibliothèques de classes .NET Framework implémentent des wrappers en code managé pour de nombreuses méthodes en code non managé (appels d'API Win32). Ces wrappers en code managé vérifient les autorisations et les paramètres de l'appelant et appellent le code non managé approprié.

    Sécurité basée sur les rôles

    Jusqu'à présent, notre discussion a porté principalement sur le rôle prépondérant de la preuve, provenant d'un assembly ou de l'environnement local, dans la sécurité du modèle d'exécution du code du .NET Framework. La sécurité basée sur les rôles définit la procédure de création d'une identité par le .NET Framework et la manière dont il autorise ou refuse l'accès aux ressources pour cette identité. Ces deux processus, communément appelés " authentification " et " autorisation ", sont les pivots du développement d'applications sécurisées pour le Web.

    Authentification

    La sécurité basée sur les rôles donne aux développeurs la possibilité de construire des scénarios d'authentification hautement personnalisés pour leurs applications. Toutes les routines d'authentification les plus courantes sont disponibles pour les applications .NET Framework par le biais d'une vaste gamme de fournisseurs d'authentification. Il s'agit en fait de routines de code qui vérifient les informations d'authentification, créent les objets Identity et Principal appropriés, et les attachent au contexte de la demande. Une fois que l'identité de l'utilisateur est déterminée, les décisions d'autorisation peuvent être prises lors de l'accès aux ressources. Les fournisseurs d'authentification peuvent aussi offrir d'autres fonctionnalités, telles que la génération de cookies, pour la maintenance de l'état de la session. Parmi les fournisseurs d'authentification pris en charge par le .NET Framework, on peut citer :

  • Authentification basée sur les formulaires (cookie) : avec ce fournisseur, les demandes non authentifiées sont redirigées vers un formulaire HTML spécifié en utilisant la redirection côté client. L'utilisateur peut ensuite fournir des informations d'authentification d'ouverture de session et republier le formulaire sur le serveur. Si l'application authentifie la demande (en utilisant la logique spécifique à l'application), ASP.NET émet un cookie qui contient les informations d'authentification ou une clé pour réacquérir l'identité du client. Les demandes suivantes sont émises avec le cookie dans les en-têtes de demande, ce qui signifie que les authentifications manuelles suivantes sont inutiles. Les informations d'authentification peuvent être vérifiées de manière personnalisée par rapport à différentes sources, par exemple une base de données SQL ou un annuaire Microsoft Exchange. Ce module d'authentification est souvent utilisé pour présenter une page d'ouverture de session à l'utilisateur.

  • Authentification Passport : il s'agit d'un service d'authentification centralisé fourni par Microsoft qui offre un système d'ouverture de session unique et des services d'abonnement pour les sites partenaires. ASP.NET, conjointement avec le kit de développement Microsoft Passport (SDK), fournit des fonctionnalités similaires à l'authentification par formulaire pour les utilisateurs de Passport.
  • IIS (Internet Information Services) : le serveur IIS de Microsoft propose plusieurs mécanismes d'authentification intégrés qui peuvent être utilisés pour fournir des identités authentifiées aux applications hébergées par IIS. S'il existe des comptes Windows correspondants, IIS peut aussi mapper automatiquement les comptes selon l'identité authentifiée. L'authentification de base, NTLM, Kerberos, l'authentification Digest et les certificats X.509 (avec SSL) figurent parmi les mécanismes d'authentification pris en charge.
  • Authentification Windows : Windows prend en charge plusieurs mécanismes d'authentification dont peuvent se servir les applications par l'intermédiaire des sous-systèmes SSPI. Il s'agit notamment des mécanismes Kerberos, NTLM et certificats X509. En outre, les développeurs peuvent écrire du code d'authentification et d'autorisation personnalisé (en combinant, par exemple, l'authentification anonyme IIS avec le fournisseur d'authentification par formulaire d'ASP.NET) ou utiliser les modules d'authentification standard déjà disponibles dans l'infrastructure ASP.NET (en combinant l'authentification NTML IIS ou Kerberos avec le fournisseur d'authentification Windows d'ASP.NET). Les fournisseurs d'authentification peuvent être configurés par application et par répertoire virtuel.

    Autorisation

    Une fois l'identité établie de manière fiable à l'aide de l'une de ces méthodes bien connues, l'accès aux ressources peut être autorisé par le biais d'une architecture extensible et souple similaire. ASP.NET propose deux méthodes d'autorisation différentes pour le code d'application :

  • l'autorisation de fichiers, dans laquelle l'emplacement de la demande est mappé au fichier physique, refusant ou octroyant l'accès en faisant correspondre les listes de contrôle d'accès (ACL, Access Control List) du fichier
  • avec l'identité de la demande2 ;
  • l'autorisation d'adresses URL, dans laquelle l'accès peut être accordé ou refusé spécifiquement en mappant les utilisateurs et les rôles aux éléments de l'espace de noms URI, y compris la méthode de la demande (GET, HEAD, POST, etc.). Par exemple, pour restreindre l'accès à l'adresse URL " http://nomserveur.com/adminpage.aspx " aux utilisateurs dans le rôle " Admin ", les contrôles des rôles d'exécution suivants peuvent être effectués dans le code :

    if(HTTPContext.IsCallerInRole("Admin"){ … } )


    Objets Principal et Identity

    Les concepts Principal et Identity du .NET Framework fournissent un modèle objet riche et fiable en matière d'identité. Un objet Principal représente le contexte de sécurité dans lequel le code est exécuté ; un objet Identity représente l'identité de l'utilisateur associé à ce contexte de sécurité. Un objet Identity est normalement créé après l'authentification réussie d'un utilisateur et relié à l'objet Principal qui sera à son tour associé à un contexte d'exécution. Le code exécuté dans un contexte spécifique peut ensuite interroger l'objet Principal au sujet du ou des rôles des objets Identity, octroyant ou refusant des autorisations en fonction de l'appartenance aux rôles.

    Cette architecture est suffisamment souple pour pouvoir définir des rôles et des objets Identity et Principal personnalisés. Par exemple, il est possible de mapper des identités à des paires nom d'utilisateur/mot de passe stockées dans une base de données ou un fichier texte. L'implémentation de l'objet GenericPrincipal répond aux besoins de ces scénarios d'autorisation hautement personnalisés et indépendants de la plate-forme.

    Le .NET Framework peut aussi tirer parti du sous-système de sécurité Windows traditionnel par le biais de l'objet WindowsPrincipal et permettre ainsi de mapper facilement des rôles aux comptes et groupes d'utilisateurs Windows existants.

    Le .NET Framework peut bien entendu emprunter l'identité de demandes de clients pour accéder aux ressources. L'emprunt d'identité demeure l'une des différences clés entre les architectures d'autorisation Windows et des solutions concurrentes telles que UNIX et Linux. Il permet aux architectes de solutions de conserver l'identité associée à un compte d'utilisateur tout au long du flux d'une application au lieu d'en confier périodiquement le contrôle au processus sous lequel est exécutée l'application.

    L'emprunt d'identité dans ASP.NET peut revêtir deux formes :
  • Emprunt d'identité par requête, ce qui signifie qu'une application peut être exécutée avec les privilèges de l'identité effectuant la demande. Cette forme d'emprunt d'identité réduit l'impact d'éventuelles violations de sécurité tout en améliorant les capacités d'audit.
  • Emprunt d'identité au niveau de l'application, où le processus de traitement exécutant l'application utilise l'identité d'un utilisateur spécifié dans la configuration. Cette forme d'emprunt d'identité diminue l'impact d'une défaillance de l'application en isolant et en protégeant d'autres applications partageant le même serveur et le même système (en d'autres termes, la défaillance de l'application n'entraîne pas nécessairement la défaillance du système)3. L'emprunt d'identité donne aux applications ASP.NET plus de précision et de souplesse lors de l'accès aux ressources, et ce de manière homogène dans tout le .NET Framework.

    Cryptographie

    Similaires aux fonctionnalités simples d'authentification et d'autorisation disponibles dans le .NET Framework, les primitives de cryptographie sont aussi facilement accessibles par le biais de bibliothèques de code managé basé sur le flux. Les développeurs peuvent s'en servir pour le cryptage, les signatures numériques, le hachage et la génération de nombres aléatoires. Des wrappers sont également disponibles pour la plupart des fonctionnalités CryptoAPI. Les algorithmes suivants sont notamment pris en charge :
  • Cryptage à clé publique (asymétrique) RSA et DSA
  • Cryptage à clé privée (symétrique) DES, TripleDES et RC2
  • Hachage MD5 et SHA1 Outre les primitives prises en charge, le .NET Framework prend en charge le cryptage au moyen d'objets de flux cryptographiques basés sur les primitives implémentées et différents modes de commentaires. Il prend aussi en charge les signatures numériques, le hachage MAC (Message Authentication Code) et à clés, les générateurs de nombres pseudo-aléatoires (PRNG, Pseudo-Random Number Generator) et les mécanismes d'authentification. Les nouvelles primitives et celles qui ne sont pas encore normalisées, telles que SHA-256 ou XMLDSIG, sont déjà prises en charge. ASP.NET prend en charge la signature et le cryptage du contenu des cookies en réponse à des problèmes sensibles affectant la sécurité des applications Web depuis longtemps.

    La disponibilité et l'étendue exhaustive de telles bibliothèques engendreront, espérons-le, une plus grande confiance vis à vis de la cryptographie pour renforcer la sécurité des applications quotidiennes. D'après notre expérience, nous pouvons affirmer qu'une stratégie de cryptographie correctement implémentée peut considérablement améliorer la sécurité de nombreux aspects d'une application.

    Domaines d'application

    Enfin, le .NET Framework propose une nouvelle méthode décisive pour séparer des parties d'une application grâce à ce que l'on appelle des domaines d'application. Les systèmes d'exploitation fournissent généralement ce mode d'isolation en exécutant chaque application dans un processus séparé, chacun avec un espace d'adressage différent, afin de les empêcher d'interférer directement les uns avec les autres. Malheureusement, pour les serveurs à forte charge, ces processus diminuent les performances du système et il peut être excessif d'exécuter un processus individuel pour chaque utilisateur qui accède au serveur.

    De par la sécurisation de type du code managé vérifié (qui garantit, entre autres, que le code ne peut pas accéder ou aller à des adresses arbitraires en mémoire), le CLR peut fournir un niveau élevé d'isolation au sein des limites du processus. Un processus unique peut contenir plusieurs domaines d'application, avec différents niveaux de confiance basés sur les preuves et objets Principal associés, sans aucun risque d'interférence malveillante entre eux. Le code exécuté dans un domaine ne peut pas directement affecter d'autres applications dans le même processus ni accéder aux ressources d'autres applications. L'ensemble du code managé est chargé dans un seul domaine d'application et exécuté conformément à la stratégie de sécurité de ce domaine.

    En somme, les domaines d'application sont une véritable aubaine pour les fournisseurs de services d'application (ASP, Application Service Provider) et les services informatiques hébergeant des applications en réseau. Ils permettent d'effectuer un contrôle de sécurité complet tout en consommant beaucoup moins de ressources que les solutions existantes.

    6. Conclusion


    Il y a bien d'autres choses dont nous aimerions parler au sujet de la sécurité de l'architecture .NET, mais un seul livre blanc n'y suffit pas ! Nous concluons ce document avec deux réflexions.

    Une conception et une administration insuffisantes compromettent encore la sécurité

    Comme nous l'avons vu dans ce livre blanc, le .NET Framework implémente en toute transparence une infrastructure de sécurité importante par le biais des composants clés de son architecture de sécurité. Cela ne veut pas dire qu'il n'est plus nécessaire de concevoir une application de manière réfléchie avec un plan de sécurité à l'esprit. Comme dans tout environnement de développement d'applications, lors de l'implémentation de code qui implique des objets d'autorisation personnalisés, des mécanismes d'autorisation ou toute autre fonctionnalité en rapport avec la sécurité, le développeur doit être familiarisé avec l'architecture de sécurité du .NET Framework afin de s'assurer que les principes de conception sont appliqués.

    En particulier, toute utilisation dangereuse de la méthode d'assertion de sécurité d'une autorisation doit être évitée. Nous recommandons de consolider et d'unifier stratégiquement les demandes ou les assertions d'une autorisation dans une application pour améliorer la sécurité et les capacités d'audit du code.

    L'implémentation de fonctionnalités cryptographiques supplémentaires au sein du .NET Framework constitue un autre point sensible à prendre en considération lors de la conception. Il est nécessaire de porter une attention particulière à ce stade. En effet, des erreurs de conception ou d'implémentation à ces niveaux peuvent porter préjudice non seulement à la sécurité d'un nouveau composant mais également à celle d'autres composants qui utilisent des éléments cryptographiques communs.

    Par exemple, une application utilisant l'authentification par cookie peut, si elle est mal conçue, permettre à des parties extérieures d'exécuter des attaques cryptographiques en texte brut contre le mécanisme d'authentification.

    Outre la conception de l'application, son déploiement et son administration sont essentiels à la sécurité. Les réseaux et les systèmes sur lesquels les applications .NET Framework sont exécutées sont toujours potentiellement vulnérables et doivent être sécurisés selon des méthodes conseillées (stratégies de gestion des comptes strictes, désactivation des services inutiles, installation régulière de correctifs, etc.). Aucun paradigme de code managé ne peut pallier une administration système négligée. Bien que le .NET Framework élimine en toute transparence de nombreuses erreurs courantes au niveau du code, il est impuissant face à des problèmes tels que l'assignation incorrecte de privilèges de comptes, la mauvaise configuration des ACL de ressources ou d'autres erreurs de configuration similaires.

    Par ailleurs, comme nous l'avons montré, le code non managé continue d'opérer hors des contraintes du modèle de sécurité du .NET Framework et peut toujours présenter des risques. Les architectes d'applications qui reposent sur du code non managé ne peuvent pas bénéficier de tous les avantages de sécurisation offerts par l'environnement managé. En règle générale, il est recommandé d'éviter d'utiliser le code non managé, de l'utiliser seulement en dernier recours et d'en vérifier les paramètres de sécurité de manière rigoureuse. Les appels aveugles et inappropriés au code non managé sont l'une des principales sources d'échec de la sécurisation des applications .NET Framework.

    La sécurité est essentielle, à tous les niveaux

    Si la sécurité n'est qu'un élément du .NET Framework, il s'agit d'un élément essentiel. Comme nous l'avons vu dans ce livre blanc, la sécurité est primordiale pour tous les systèmes en réseau actuels et le .NET Framework, s'il est utilisé correctement, peut fournir aux développeurs, aux administrateurs et aux utilisateurs finals l'assurance que leurs applications pourront résister aux attaques de sécurité présentes et futures. Pour cela, le .NET Framework offre de nouvelles approches pour gérer le comportement des logiciels, notamment les fonctionnalités de sécurité basée sur les preuves et les rôles.

    Au nom de Foundstone et de CORE, nous espérons que cette brève exploration de l'architecture de sécurité du .NET Framework a été informative et qu'elle pourra vous aider à concevoir et à développer la prochaine génération de logiciels. D'après notre propre analyse et nos interactions poussées avec les architectes Microsoft du .NET Framework, nous sommes persuadés que la sécurité des applications s'améliorera à mesure que la migration sera réalisée vers le .NET Framework et que l'équipe en charge du .NET Framework accordera à la sécurité la plus haute priorité au fil de l'évolution de la technologie informatique.

    7. Ressources supplémentaires


    MSDN .NET Developer Center http://www.microsoft.com/france/msdn/technologies/technos/net/default.asp
    Communauté GotDotNet (en anglais) http://www.gotdotnet.com/
    Visual Studio .NET http://www.microsoft.com/france/vstudio/default.asp
    Référence .NET Framework http://www.microsoft.com/france/msdn/technologies/technos/framework/default.asp
    Site principal ASP.NET (en anglais) http://www.asp.net/
    Site ASP.NET MSDN http://www.microsoft.com/france/msdn/technologies/technos/asp/default.asp
    Site de solutions pour développeurs IBuySpy par Vertigo Software (en anglais) http://ibuyspy.com/
    Foundstone (en anglais) http://www.foundstone.com
    Core Security Technologies (en anglais) http://www.corest.com



    1. Les demandes d'autorisation Minimal, Optional et Refuse sont strictement supplémentaires.
    2. L'autorisation de fichiers est uniquement utilisée conjointement avec l'authentification Windows puisque les autres mécanismes d'authentification ne définissent généralement pas un jeton d'accès Windows par utilisateur.
    3. Il est à noter que les informations d'authentification sont stockées dans la configuration en texte clair. Pour cela, il est plus approprié de configurer le compte anonyme ou d'appeler un objet ServicedComponent exécuté comme une identité fixe (fixed) dans une application serveur COM+.
  • Responsable bénévole de la rubrique Microsoft DotNET : Hinault Romaric -