Création de composants distants sécurisés
Sur cette page
Dans ce module
Objectifs
S'applique à
Présentation
Menaces et contre-mesures
Problèmes de conception
Validation des entrées
Authentification
Autorisation
Données sensibles
Refus de service
Gestion des exceptions
Audit et journalisation
Considérations sur la sécurité d'accès au code (CAS)
Résumé
Informations complémentaires
Dans ce module
Microsoft® .NET Framework Remoting fournit une structure riche et extensible permettant à des objets résidant dans différents domaines d'application (AppDomains), différents processus et sur différents ordinateurs de communiquer de façon transparente. .NET Remoting offre un modèle de programmation puissant et simple ainsi qu'une prise en charge à l'exécution qui rend ces interactions transparentes.
Bien que l'infrastructure Remoting n'ait pas de mécanisme d'authentification ni d'autorisation par défaut, si vous hébergez des composants distants avec ASP.NET et que vous utilisez HttpChannel pour communiquer, vous pouvez utiliser les services d'authentification et d'autorisation fournis par Internet Information Services (IIS) et ASP.NET.
Ce module présente des recommandations et des conseils pour vous aider à créer des composants distants sécurisés. Cela concerne aussi bien les composants utilisant ASP.NET et HttpChannel que ceux qui utilisent des exécutables personnalisés et TcpChannel.
Objectifs
Ce module vous permettra :
-
de concevoir et de déployer des composants sécurisés ;
-
de protéger les données sensibles transférées par et vers des composants distants ;
-
de choisir un processus hôte approprié ;
-
de comparer l'utilisation de HttpChannel et de TcpChannel ;
-
de limiter les risques d'attaques par sérialisation et d'attaques MarshalByRefObject ;
-
d'authentifier et d'autoriser les appelants ;
-
de protéger les composants distants des attaques de refus de service ;
-
de savoir quoi faire en situation de confiance partielle alors que les composants Remoting exigent une confiance totale ;
-
de connaître les contre-mesures à appliquer pour faire face aux menaces auxquelles Remoting est couramment confronté, notamment les accès non autorisés, les écoutes clandestines et les manipulations de paramètres.
S'applique à
Ce module s'applique aux produits et technologies suivants :
-
Microsoft Windows® 2000 Server et Microsoft Windows Server? 2003
-
Microsoft .NET Framework 1.1 et ASP.NET 1.1
Présentation
L'infrastructure de Microsoft .NET Framework Remoting ne dispose d'aucun mécanisme d'authentification ni d'autorisation. Toutefois, si vous hébergez des composants distants avec ASP.NET et que vous utilisez HttpChannel pour communiquer, vous pouvez utiliser les services d'authentification et d'autorisation fournis par IIS et ASP.NET.
Si les performances sont pour vous une priorité, vous pouvez envisager d'utiliser un hôte personnalisé et TcpChannel. Ne choisissez cette solution que si les sous-systèmes sont fiables, c'est-à-dire si la gamme des appelants possibles est soigneusement contrôlée par des techniques hors-bande (les stratégies IPSec, par exemple) qui n'autorisent que les communications provenant des serveurs Web spécifiés. Avec TcpChannel, vous devrez créer vos propres mécanismes d'authentification et d'autorisation. Cette option est contraire au principe selon lequel il est préférable d'utiliser des services de sécurité testés et éprouvés, au niveau de la plate-forme ; elle exige en outre un effort de développement important.
Ce module propose des recommandations et des conseils pour vous aider à créer des composants distants sécurisés. Cela concerne aussi bien les composants utilisant ASP.NET et HttpChannel que ceux qui utilisent des exécutables personnalisés et TcpChannel. Le modèle de déploiement typique utilisé dans ce module est décrit à la figure 13.1 : les objets distants sont placés sur un serveur d'applications de niveau intermédiaire et traitent les requêtes provenant des clients d'applications Web ASP.NET et des applications Windows déployées au sein de l'entreprise.
Figure 13.1
Déploiement d'accès distant typique
Dans ce scénario courant, le composant distant traite les requêtes émanant des applications Web frontales. Dans ce cas, ASP.NET sur le serveur Web gère l'authentification et l'autorisation des appelants. De plus, les applications Windows Édition Entreprise accèdent souvent aux composants distants de niveau intermédiaire.
Menaces et contre-mesures
Pour créer des solutions sécurisées utilisant la technologie d'accès distant, vous devez connaître les menaces associées. Les principales menaces pesant sur les composants utilisant l'accès distant sont les suivantes :
-
Accès non autorisé
-
Écoute clandestine du réseau
-
Manipulation des paramètres
-
Sérialisation
La figure 13.2 représente ces menaces.
Figure 13.2
Principales menaces liées à l'accès distant
Accès non autorisé
Les composants distants qui fournissent des informations sensibles ou restreintes doivent authentifier et autoriser leurs appelants pour empêcher les accès non autorisés. Les failles d'authentification et d'autorisation peuvent être exploitées pour accéder sans autorisation aux opérations et aux informations sensibles.
Vulnérabilités
Du fait des vulnérabilités suivantes, votre solution d'accès distant est susceptible d'être victime d'accès non autorisés :
-
Pas d'authentification au niveau de l'application (c'est un hôte de service Windows personnalisé qui est utilisé).
-
Aucune stratégie IPSec ne limite les ordinateurs autorisés à communiquer avec le serveur d'applications de niveau intermédiaire qui héberge les composants distants.
-
Pas d'autorisation basée sur les rôles.
-
Pas d'autorisation d'accès aux fichiers restreignant l'accès aux points finaux distants.
-
Approbation des objets IPrincipal transmis par le client.
Contre-mesures
Des contre-mesures peuvent être mises en œuvre pour empêcher les accès non autorisés :
-
S'assurer que l'application Web frontale authentifie et autorise les clients et que les communications vers les serveurs d'applications de niveau intermédiaire sont restreintes au moyen de stratégies IPSec. Ces mesures garantissent que seul le serveur Web peut accéder directement au serveur d'applications de niveau intermédiaire.
-
Utiliser ASP.NET pour héberger les composants distants et utiliser l'authentification Windows pour restreindre l'accès à ces derniers.
-
Utiliser la propriété FileAuthorizationModule d'ASP.NET. Cela exige une configuration spécifique et la création d'un fichier physique (.rem or .soap) qui corresponde au point final distant.
-
Utiliser l'autorisation basée sur les rôles pour restreindre l'accès aux composants distants, à leurs classes et à leurs méthodes. Pour ce faire, utilisez l'autorisation d'accès à l'URL pour contrôler l'accès au point final distant (.rem ou .soap) ou, au niveau de la classe ou de la méthode, en utilisant les demandes d'autorisation de l'entité principale.
-
Ne pas faire confiance aux objets IPrincipal transmis par un client, à moins que le client ne soit fiable. Ce n'est en général le cas que si IPSec est utilisé pour limiter le nombre d'ordinateurs clients.
Écoute clandestine du réseau
L'écoute clandestine permet aux pirates de voir les messages de requêtes et de réponses circulant sur le réseau, depuis et vers le composant distant. Par exemple, un pirate peut utiliser un logiciel de surveillance du réseau pour récupérer des données sensibles. Il peut s'agir de données d'application sensibles ou d'informations d'authentification.
Vulnérabilités
Certaines vulnérabilités sont susceptibles de permettre les écoutes clandestines et peuvent poser des problèmes de sécurité :
-
Authentification de base réalisée sur un canal de communication non crypté
-
Pas de cryptage au niveau du transport
-
Pas de cryptage au niveau de l'application
Contre-mesures
Des contre-mesures peuvent être mises en œuvre pour empêcher l'écoute clandestine du réseau :
-
Utiliser un cryptage au niveau du transport, comme SSL ou IPSec. Si vous utilisez SSL, vous devrez aussi utiliser un hôte ASP.NET et HttpChannel. IPSec peut être utilisé avec des hôtes personnalisés et TcpChannel.
-
Crypter la requête au niveau de l'application pour préserver la confidentialité. Vous pouvez par exemple créer un récepteur de cryptage personnalisé pour crypter une partie de la charge utile du message.
Manipulation des paramètres
On entend par manipulation des paramètres la modification non autorisée des données envoyées entre le client et le composant distant. Un pirate peut par exemple manipuler le message de requête destiné au composant distant en l'interceptant alors qu'il est en transit.
Vulnérabilités
Les vulnérabilités rendant possibles les manipulations de paramètres sont notamment :
-
Messages sans signature numérique, donc sans protection infalsifiable.
-
Messages non cryptés, donc sans garantie de confidentialité ni protection infalsifiable.
Contre-mesures
Des contre-mesures peuvent être mises en œuvre pour éviter la manipulation des paramètres :
-
Signer numériquement les messages. La signature numérique sert, côté destinataire, à vérifier que le message n'a pas été falsifié pendant le transit.
-
Crypter les messages pour préserver leur confidentialité et les doter d'une protection infalsifiable.
Sérialisation
La sérialisation est un processus consistant à convertir l'état interne d'un objet en un flux d'octets plat. L'infrastructure d'accès distant utilise les services de sérialisation de NET Framework pour transférer des objets entre le client et le serveur. Il est possible qu'un code malveillant injecte un flux de données sérialisées dans votre serveur pour le forcer à réaliser des opérations non souhaitées. Par exemple, un code malveillant côté client peut initialiser un objet qui, une fois désérialisé sur le serveur, forcera ce dernier à consommer des ressources serveur ou à exécuter un code malveillant.
Vulnérabilités
La principale vulnérabilité pouvant permettre la réussite des attaques par sérialisation provient du fait que le serveur fait confiance aux flux de données sérialisées et ne valide pas les données récupérées dans le flux.
Contre-mesures
Pour éviter que les attaques par sérialisation ne réussissent, il faut valider chaque élément de donnée lorsqu'il est désérialisé sur le serveur. Validez le type, la longueur, le format et la plage de chaque élément.
Problèmes de conception
Avant de commencer à développer des composants distants, vous devez prendre en compte un certain nombre de points relatifs à la conception. Les principales règles de sécurité sont les suivantes :
-
Ne pas exposer des objets distants sur Internet.
-
Utiliser HttpChannel pour profiter de la sécurité ASP.NET..
-
N'utiliser TcpChannel qu'avec des serveurs sécurisés.
Ne pas exposer des objets distants sur Internet
Hébergez vos objets distants sur des serveurs d'applications de niveau intermédiaire exclusivement, des serveurs qui ne soient pas directement accessibles par Internet et auxquels ne puissent accéder que les applications Web frontales et les services Web. Si vous avez besoin d'exposer une fonctionnalité fournie par un objet distant pour des clients Internet, utilisez un service Web pour envelopper l'objet de niveau intermédiaire et exposez le service Web sur Internet.
Utiliser HttpChannel pour profiter de la sécurité ASP.NET
Si la sécurité n'est pas votre priorité, utilisez ASP.NET pour héberger les objets distants. Cela permet d'utiliser les fonctions d'authentification, d'autorisation et de communication sécurisée d'ASP.NET et d'IIS. Par exemple, vous pouvez utiliser l'authentification Windows et SSL pour la confidentialité et l'intégrité des requêtes et des réponses envoyées sur le réseau.
Utiliser TcpChannel avec des serveurs sécurisés exclusivement
Si, pour des questions de performances, vous utilisez TcpChannel avec un processus hôte personnalisé, souvenez-vous que cette solution ne propose aucun service d'authentification intégré.
C'est la raison pour laquelle il ne faut utiliser TcpChannel qu'avec des serveurs sécurisés, où le service ou l'application Web en amont authentifie et autorise les appelants d'origine avant d'appeler vos composants de niveau intermédiaire. Pour sécuriser ce scénario, utilisez IPSec pour l'authentification au niveau de la machine et pour sécuriser les communications. La stratégie IPSec ne doit autoriser le trafic qu'entre le(s) serveur(s) sélectionné(s) et l'hôte du composant distant de niveau intermédiaire. Ce scénario avec serveur sécurisé est illustré à la figure 13.3.
Figure 13.3
Accès distant dans un scénario avec serveur sécurisé
Pour plus d'informations sur IPSec, reportez-vous à la « Procédure : utilisation d'IPSec » dans la section « Procédures » de ce guide.
À propos de TcpChannel
Si vous utilisez un hôte exécutable personnalisé et TcpChannel et que vous ne pouvez pas compter sur une application Web en amont pour authentifier et autoriser le client, il vous faut développer vos propres solutions d'authentification et d'autorisation.
Vous pouvez décider de transmettre les objets principaux en tant que paramètres des méthodes ou dans le contexte d'appel. N'optez pour cette solution que si votre environnement est sécurisé, pour éviter qu'un code malveillant côté client ne crée un objet IPrincipal avec des rôles élevés et ne l'envoie à votre serveur. Votre implémentation serveur doit être capable de faire confiance aux objets IPrincipal avant de les utiliser pour l'autorisation basée sur les rôles.
Une autre approche possible consiste à utiliser les services sous-jacents de l'interface SSPI (fournisseur de la prise en charge de sécurité). Pour plus d'informations sur cette approche, reportez-vous à l'article de MSDN « .NET Remoting Security Solution, Part 1: Microsoft.Samples.Security.SSPI Assembly », à l'adresse suivante : http://msdn.microsoft.com/library/en-us/dndotnet/html/remsspi.asp.
Pour garantir la sécurité des communications lorsque vous utilisez TcpChannel, utilisez IPSec ou un récepteur de canal de cryptage personnalisé pour crypter les données des requêtes.
Validation des entrées
En cas de scénario avec serveurs sécurisés, pour lesquels il est recommandé d'utiliser des solutions d'accès distant, ce sont en général les applications Web frontales qui se chargent de la validation des entrées. Les données sont entièrement validées avant d'être transmises aux composants distants. Si vous pouvez garantir que les données transmises à un composant distant ne peuvent provenir que de l'intérieur des limites sécurisées, vous pouvez laisser le code amont se charger de la validation des entrées.
En revanche, si des applications clientes de l'entreprise peuvent accéder à votre solution d'accès distant de façon arbitraire, vos composants réseau devront valider la saisie et rester vigilants vis-à-vis des attaques par sérialisation et des attaques MarshalByRefObject.
Attaques par sérialisation
Vous pouvez transmettre des paramètres d'objets à des composants distants soit en utilisant le contexte d'appel, soit en les transférant, via des paramètres d'entrée normaux, aux méthodes exposées par les composants en question. Il est possible qu'un client malveillant sérialise un objet puis le transmette à un composant distant avec l'intention explicite de le prendre en défaut ou de l'amener à effectuer une opération non souhaitée. À moins que vous ne puissiez faire confiance au client, validez soigneusement chaque élément de champ de l'objet désérialisé, parce que le paramètre d'objet est créé sur le serveur.
Attaques MarshalByRefObject
Les objets dérivés de System.MarshalByRefObject ont besoin d'une URL pour renvoyer les appels vers le client. Il peut arriver que l'URL de rappel soit usurpée pour que le serveur se connecte à un autre ordinateur client, par exemple un ordinateur situé derrière un pare-feu.
Vous pouvez limiter les risques d'attaques par sérialisation et par MarshalByRefObject grâce à la version 1.1 de .NET Framework, en définissant l'attribut typeFilterLevel de l'élément <formatter> sur Low. Cela revient à donner à l'infrastructure d'accès distant .NET Framework l'instruction de ne sérialiser que les objets dont elle a besoin pour exécuter l'invocation de méthode, de rejeter les objets personnalisés prenant en charge la sérialisation que vous créez et de les placer dans le contexte d'appel ou de les transmettre sous forme de paramètres. Vous pouvez configurer ce paramètre dans Web.config ou par programmation (voir ci-dessous).
<formatter ref="binary" typeFilterLevel="Low" />
ou
BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider(); provider.TypeFilterLevel = TypeFilterLevel.Low;
Authentification
Si votre composant distant expose des opérations ou des données sensibles, il doit authentifier ses appelants pour prendre en charge l'autorisation. L'infrastructure d'accès distant .NET Framework ne propose aucun modèle d'authentification. C'est à l'hôte de gérer l'authentification. Par exemple, vous pouvez utiliser ASP.NET pour utiliser les fonctions d'authentification d'ASP.NET et d'IIS.
Si vous utilisez un hôte de service Windows, développez une solution d'authentification personnalisée.
Hébergement ASP.NET
Les directives suivantes s'appliquent si vous utilisez un hôte ASP.NET et HttpChannel :
-
Désactivez l'authentification anonyme sur IIS.
-
Configurez ASP.NET pour l'authentification Windows.
-
Configurez les informations d'authentification du client.
-
Améliorez les performances en partageant les connexions authentifiées.
-
Forcez les clients à s'authentifier à chaque appel.
-
Contrôlez l'utilisation des connexions authentifiées.
Désactivation de l'authentification anonyme sur IIS
Pour garantir que les appelants sont authentifiés par IIS, assurez-vous que le répertoire virtuel de votre application ne prend par en charge l'authentification anonyme. Sur Windows Server 2003, assurez-vous également que l'authentification .NET Passport est désactivée.
Puisque vous avez désactivé l'authentification anonyme d'IIS, vous pouvez utiliser l'un des mécanismes d'authentification pris en charge par IIS pour authentifier les appelants sur HttpChannel, en utilisant par exemple l'authentification Basic, Digest ou celle intégrée à Windows. Pour éviter que les informations d'authentification ne soient transmises via le réseau et utiliser les politiques de sécurité de Windows 2000 sur les comptes et les mots de passe, utilisez l'authentification intégrée de Windows.
Configuration d'ASP.NET pour l'authentification Windows.
Configurez votre application pour l'authentification Windows avec le paramètre suivant dans Web.config :
<authentication mode="Windows" />
Vous ne pouvez pas utiliser l'authentification des formulaires ni celle de Passport parce qu'elles exigent une redirection vers une page de connexion.
Remarque : lorsque vous utilisez l'authentification Windows, il est recommandé d'activer l'autorisation d'accès au fichier. Pour plus d'informations, reportez-vous à la rubrique « Autorisation », plus loin dans ce module.
Configuration des informations d'authentification du client
Pour réussir à communiquer avec un composant distant configuré pour l'authentification Windows, le client doit configurer le proxy distant avec les informations d'authentification à utiliser. Sans cela, une erreur de refus d'accès est générée.
Vous pouvez configurer les informations d'authentification par défaut pour qu'elles utilisent le jeton de processus ou le thread actuel ou définir des informations d'authentification explicites.
Utilisation des informations d'authentification par défaut
Pour utiliser le jeton de processus du client (ou le jeton de thread si le thread client emprunte une identité), définissez la propriété useDefaultCredentials du proxy du client sur true. Cela a pour résultat d'utiliser CredentialsCache.DefaultCredentials lorsque le client reçoit une demande d'authentification du serveur. Vous pouvez configurer le proxy soit en utilisant le fichier de configuration, soit par programmation en code. Pour configurer le proxy en externe, utilisez l'élément suivant dans le fichier de configuration du client :
<channel ref="http client" useDefaultCredentials="true" />
Pour définir par programmation les informations d'authentification qui seront utilisées par défaut, utilisez le code suivant :
IDictionary channelProperties; channelProperties = ChannelServices.GetChannelSinkProperties(proxy); channelProperties ["credentials"] = CredentialCache.DefaultCredentials;
si vous utilisez des informations d'authentification par défaut dans une application client ASP.NET configurée pour l'emprunt d'identité, c'est le jeton d'emprunt d'identité au niveau du thread qui est utilisé. Cela exige une délégation Kerberos.
Utilisation d'autres informations d'authentification
Pour utiliser des informations d'authentification spécifiques lorsque vous appelez un objet distant, désactivez l'utilisation des informations d'authentification par défaut dans le fichier de configuration en utilisant le paramètre suivant.
<channel ref="http" useDefaultCredentials="false" />
Remarque : les paramètres entrés par programmation sont toujours prioritaires sur les paramètres du fichier de configuration.
Ensuite, utilisez le code suivant pour que le proxy utilise les informations d'authentification spécifiques :
IDictionary channelProperties =
ChannelServices.GetChannelSinkProperties(proxy);
NetworkCredential credentials;
credentials = new NetworkCredential("username", "password", "domain");
ObjRef objectReference = RemotingServices.Marshal(proxy);
Uri objectUri = new Uri(objectReference.URI);
CredentialCache credCache = new CredentialCache();
// Remplacez "authenticationType" par "Negotiate", "Basic", "Digest",
// "Kerberos" ou "NTLM"
credCache.Add(objectUri, "authenticationType", credentials);
channelProperties["credentials"] = credCache;
channelProperties["preauthenticate"] = true;
Amélioration des performances grâce au partage des connexions authentifiées
Lorsque vous définissez useDefaultCredentials="true", définissez aussi la propriété useAuthenticatedConnectionSharing côté client sur true. Cela permet au serveur de réutiliser les connexions authentifiées plutôt que d'authentifier chaque appel entrant.
<channel ref="http client" useAuthenticatedConnectionSharing="true" >
Ceci ne fonctionne qu'avec HttpChannel sur la version 1.1 de .NET Framework.
Forcer les clients à s'authentifier à chaque appel
Définissez unsafeAuthenticatedConnectionSharing sur false de sorte que les clients ne puissent pas fournir leurs propres informations d'authentification et leur nom de groupe de connexion au serveur.
Si vous définissez cette propriété sur true, les clients non authentifiés ont la possibilité de s'authentifier auprès du serveur en utilisant les informations d'authentification d'un client authentifié précédemment. Ce paramètre est ignoré si la propriété useAuthenticatedConnectionSharing est définie sur true. Ce paramètre a un impact sur les performances puisqu'il ferme chaque connexion avec le serveur : les clients doivent donc s'authentifier à chaque appel. Si vous utilisez ce paramètre, spécifiez également un ConnectionGroupName pour chaque utilisateur de la connexion.
<channel ref="http client" unsafeAuthenticatedConnectionSharing="false" >
Ceci ne fonctionne qu'avec HttpChannel sur la version 1.1 de .NET Framework.
Contrôle de l'utilisation des connexions authentifiées
Si vous définissez unsafeAuthenticationConnectionSharing sur true, proposez un nom pour grouper les connexions authentifiées en définissant la propriété connectionGroupName. Si vous utilisez des informations d'authentification par défaut, connectionGroupName est défini en fonction du compte utilisateur utilisé pour exécuter le thread.
<channel ref="http client" connectiongroupname="<name>" />
Hébergement d'un processus personnalisé
Si vous utilisez un hôte de service Windows et TcpChannel, utilisez cette approche uniquement si vos serveurs sont sécurisés ou proposez un schéma d'authentification. Les directives suivantes s'appliquent si vous utilisez un hôte personnalisé et TcpChannel :
-
Ne transmettez pas par le réseau des informations d'authentification en clair.
-
Ne faites pas confiance aux objets IPrincipal transmis par le client.
Ne transmettez pas par le réseau des informations d'authentification en clair
Si votre serveur a besoin des informations d'authentification du client en clair, cryptez-les avant de les envoyer sur le réseau. Si votre serveur a besoin de valider les informations d'authentification du client, utilisez un schéma demande/réponse pour valider les informations d'authentification sur le serveur. Cela peut impliquer l'envoi d'un hachage, d'un hachage indexé, d'une valeur à usage unique cryptée (nonce) avec le hachage ou l'utilisation d'une signature numérique.
Toutefois, même dans ces scénarios, vous devez toujours utiliser un canal de communication crypté pour éviter les attaques par relecture.
Ne pas faire confiance aux objets IPrincipal transmis par le client
Soyez prudents si vous transmettez des objets IPrincipal du client vers le serveur. Un code non approuvé pourrait créer un objet IPrincipal, l'initialiser avec des rôles et l'envoyer au serveur. Si le serveur accepte l'objet IPrincipal sans le valider, le client peut élever les privilèges de l'appelant sur le serveur. Par exemple, un appelant malveillant pourrait créer un objet IPrincipal contenant des noms de rôles courants et à privilèges élevés comme Administrators, Managers, ExpenseReportApprovers et Supervisors. Lorsque l'objet est reçu sur le serveur et placé dans la propriété Thread.CurrentPrincipal, le code appelant IsInRole sur cet objet pourrait être forcé d'exécuter un code privilégié.
Autorisation
Dans le contexte de l'accès distant .NET Framework, vous pouvez appliquer des autorisations pour restreindre la capacité d'accès des ordinateurs et des utilisateurs aux fonctionnalités exposées par vos objets distants. Utilisez les directives suivantes pour vous assurer que votre approche d'autorisation est efficace :
-
Utilisez IPSec pour le contrôle d'accès au niveau de la machine.
-
Activez l'autorisation d'accès aux fichiers pour contrôler l'accès des utilisateurs.
-
Autorisez les utilisateurs via des vérifications de rôle relatives à l'entité principale.
-
Envisagez de limiter les accès distants.
Utilisation d'IPSec contrôler les accès au niveau de la machine
Vous pouvez définir une stratégie IPSec pour garantir que seul un serveur Web ou un groupe de serveurs sélectionnés pourront se connecter au serveur d'applications qui héberge vos objets distants. Cela réduit considérablement la zone exposée aux attaques.
Activation de l'autorisation d'accès aux fichiers pour contrôler l'accès des utilisateurs
Si votre objet distant est hébergé par ASP.NET et utilise l'authentification Windows, vous pouvez configurer des listes de contrôle d'accès (ACL) sur les points finaux distants pour autoriser les appelants. Les ACL sont évaluées à chaque requête par la propriété FileAuthorizationModule d'ASP.NET. Dans des circonstances normales, aucun fichier physique ne représente les points finaux distants auxquels vos clients se connectent. Une requête de fichier possédant une extension .rem ou .soap suffit pour qu'IIS soit capable d'acheminer la requête vers l'infrastructure d'accès distant et l'application ASP.NET appropriée, conformément aux mappages d'application définis dans la métabase d'IIS.
-
Pour configurer la propriété FileAuthorizationModule d'ASP.NET pour l'accès distant .NET Framework
-
Créez un fichier à la racine du répertoire virtuel de l'application et donnez-lui le nom de la valeur spécifiée dans la propriété objectUri de Web.config (RemoteMath.rem, par exemple).
La propriété objectUri se trouve dans le fichier Web.config utilisé pour configurer l'objet distant sur le serveur. Recherchez l'élément <wellknown>, comme indiqué dans l'exemple suivant :<wellknown mode="SingleCall" objectUri="RemoteMath.rem" type="RemotingObjects.RemoteMath, RemotingObjects, Version=1.0.000.000 Culture=neutral, PublicKeyToken=4b5ae668c251b606"/> -
Ajoutez la ligne suivante en haut du fichier et enregistrez le fichier.
<%@ webservice class="YourNamespace.YourClass" ... %>
-
Ajoutez une ACL correctement configurée au fichier, avec l'Explorateur Windows, pour déterminer les utilisateurs ou les groupes d'utilisateurs autorisés ou pas à accéder à l'objet.
-
Autorisation des utilisateurs avec vérifications de rôle relatives à l'entité principale
L'approche FileAuthorizationModule décrite plus haut permet de contrôler les personnes qui peuvent ou ne peuvent pas accéder à l'objet distant. Si vous souhaitez mettre en œuvre une autorisation plus nuancée pouvant être appliquée au niveau de la méthode, vous pouvez réaliser des vérifications d'autorisation en utilisant l'objet IPrincipal attaché à la requête en cours.
Si votre objet distant est hébergé par ASP.NET et que vous utilisez l'authentification Windows, un objet IPrincipal basé sur l'identité Windows de l'appelant authentifié est automatiquement créé et attaché à Thread.CurrentPrinicipal.
Si vous utilisez un hôte personnalisé, créez un objet IPrincipal pour représenter l'utilisateur authentifié. Le fonctionnement dépend de votre approche d'authentification. Par exemple, si vous utilisez un transport par canal nommé, vous pouvez emprunter l'identité des appelants pour créer un objet IPrincipal.
Si l'objet IPrincipal est en place, vous pouvez exécuter l'autorisation en utilisant des demandes d'autorisation sur l'entité principale, de façon à la fois déclarative et impérative, et vous pouvez appeler IPrincipal.IsInRole.
Envisager de limiter les accès distants
Dans certains scénarios, si vous utilisez l'accès distant pour les communications inter-processus ou entre les domaines d'application sur un seul ordinateur, vous pouvez définir rejectRemoteRequests sur true pour garantir que les ordinateurs distants ne pourront pas accéder à votre objet, comme indiqué ci-dessous.
<channel ref="http server" rejectRemoteRequests="true" />
Données sensibles
Si vous avez besoin de transmettre des données sensibles via un canal de communication d'accès distant sur un réseau, pour éviter les écoutes clandestines, pensez à la confidentialité et à l'intégrité des données. Trois possibilités s'offrent à vous ; votre choix sera certainement guidé par votre environnement de déploiement et l'hôte que vous avez choisi. Vos options sont les suivantes :
-
Utiliser IPSec
-
Utiliser SSL
-
Utiliser un récepteur de cryptage personnalisé
Utilisation d'IPSec
Vous pouvez utiliser les stratégies IPSec pour sécuriser les canaux de communication vers vos objets distants (le canal partant d'un serveur Web, par exemple). IPSec peut servir à crypter tous les paquets TCP envoyés sur une connexion donnée, dont les paquets envoyés par et vers vos objets distants. Cette solution est généralement utilisée par les infrastructures des centres de données intranet et Internet sécurisées ; elle présente l'avantage de n'exiger aucun effort de codage supplémentaire.
Autre avantage de l'utilisation d'IPSec : il offre une solution de communication sécurisée, quel que soit l'hôte de l'objet distant et le type de canal. Par exemple, la solution fonctionne si vous utilisez TcpChannel et un hôte personnalisé.
Utilisation de SSL
Si vous utilisez l'hôte ASP.NET, vous pouvez utiliser IIS pour configurer le répertoire virtuel de votre application pour qu'il exige SSL. Par conséquent, les clients devront utiliser une connexion HTTPS pour communiquer avec vos objets distants.
Utilisation d'un récepteur de cryptage personnalisé
Si vous ne disposez pas d'un centre de données sécurisé avec des stratégies IPSec qui protègent les canaux de communication entre vos serveurs, vous pouvez opter pour une autre stratégie : implémenter un récepteur de cryptage personnalisé. Cette option vous intéresse particulièrement si vous avez besoin de ne sécuriser que les parties sensibles de messages transmis des clients vers les serveurs plutôt que l'ensemble de la charge utile. Cette approche est décrite à la figure 13.4.
Figure 13.4
Utilisation de récepteurs de cryptage personnalisés
Un récepteur de cryptage est un récepteur de canal personnalisé que vous pouvez utiliser lorsque vous utilisez un hôte personnalisé avec TcpChannel. Côté client, le récepteur crypte les données des requêtes avant qu'elles ne soient envoyées au serveur et décrypte les données des éventuelles réponses reçues du serveur. Côté serveur, le récepteur décrypte les données des requêtes puis crypte les données des réponses.
Implémentation d'un récepteur de cryptage personnalisé
Le récepteur doit utiliser le cryptage asymétrique pour échanger les clés de cryptage au niveau de la session. Après avoir échangé une clé de session, le client et le serveur conservent une copie de la clé et chaque côté peut choisir de créer une nouvelle clé à tout moment pendant la durée de vie du récepteur de canal. Le serveur doit conserver une clé différente pour chaque client avec lequel il communique.
Les étapes suivantes décrivent l'approche de base nécessaire à l'implémentation d'un récepteur de cryptage personnalisé :
-
Créer une paire de clés publique/privée pour la solution.
const int AT_KEYEXCHANGE = 1; CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "<container name>"; cspParams.KeyNumber = AT_KEYEXCHANGE; cspParams.ProviderName = "Microsoft Base Cryptographic Provider v1.0"; cspParams.ProviderType = PROV_RSA_FULL; RSACryptoServiceProvider rsaServerSide = new RSACryptoServiceProvider(cspParams); rsaServerSide.PersistKeyInCsp = true; Console.WriteLine(rsaServerSide.ToXmlString(true)); // Écrit la clé publique -
Exposer la clé publique afin que les clients puissent l'utiliser.
Le client conserve une copie de la clé publique dans un fichier. -
Initialiser le récepteur de canal client et créer une clé aléatoire pour le cryptage.
byte[] randomKey = new byte[size]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(randomKey);
-
Crypter la clé aléatoire avec la clé publique de votre serveur. Utiliser IClientChannelSink.ProcessMessage pour envoyer la clé cryptée au serveur.
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp); rsa.FromXmlString("<server's public key>"); AsymmetricKeyExchangeFormatter formatter = new RSAPKCS1KeyExchangeFormatter(rsa); byte[] encryptedSessionKey = formatter.CreateKeyExchange(_sessionKey); -
Initialiser le récepteur de canal du serveur et créer un objet RSA en utilisant le nom du conteneur de la clé spécifique.
const int AT_KEYEXCHANGE = 1; CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "<container name>"; cspParams.KeyNumber = AT_KEYEXCHANGE; cspParams.ProviderName = "Microsoft Base Cryptographic Provider v1.0"; cspParams.ProviderType = PROV_RSA_FULL; RSACryptoServiceProvider rsaServerSide = new RSACryptoServiceProvider(cspParams);
-
Récupérer la clé cryptée auprès du client. La clé est normalement envoyée dans les en-têtes de la requête.
-
Décrypter la clé de cryptage de la session en utilisant la clé privée du serveur.
AsymmetricKeyExchangeDeformatter asymDeformatter = new RSAPKCS1KeyExchangeDeformatter(_rsa); byte[] decryptedSessionKey = asymDeformatter.DecryptKeyExchange( <encrypted key>); -
Utiliser un mécanisme pour mapper les clients sur les clés de cryptage, par exemple, en utilisant une table de hachage.
Le client et le serveur partagent alors une clé de cryptage et peuvent crypter et décrypter les appels de méthode. Régulièrement tout au long de la durée de vie de l'objet, de nouvelles clés peuvent et doivent être créées.
Refus de service
Les attaques par refus de service peuvent se produire lorsqu'un client malveillant crée plusieurs objets et ne cesse de renouveler la durée de leur bail pour consommer des ressources serveur. Les objets distants côté serveur disposent d'un bail par défaut. Dans cette situation, un client peut renouveler le bail éternellement. Il est toutefois possible d'implémenter l'interface ILease sur le serveur et de contrôler explicitement les sponsors et les renouvellements. Pour ce faire, substituez InitializeLifetimeService sur votre objet MarshalByRefObject. L'infrastructure d'accès distant appelle cette méthode quand l'objet est créé. Le bail peut aussi être défini par programmation en utilisant l'élément <lifetime>.
Gestion des exceptions
Veillez à ne pas renvoyer tous les détails de l'exception à l'appelant. Si vous utilisez un hôte ASP.NET, assurez-vous qu'ASP.NET est configuré pour que des messages d'erreur génériques soient renvoyés au client, comme indiqué ci-dessous.
<configuration>
<system.runtime.remoting>
<!-- Les valeurs valides pour l'attribut mode sont :
on - les appelants reçoivent les messages d'erreur par défaut
remoteOnly - les clients sur le même ordinateur que le composant distant reçoivent
les informations détaillées de l'exception. Les appels distants reçoivent un
message d'erreur par défaut
off - les appelants reçoivent les informations détaillées de l'exception -->
<customErrors mode="on"/>
</system.runtime.remoting>
</configuration>
Utilisez mode="on" ou mode="remoteOnly". N'utilisez pas mode="off" sur les serveurs de production.
Utilisation d'un récepteur de canal personnalisé
Vous pouvez implémenter un récepteur de canal personnalisé pour consigner les exceptions côté client et/ou côté serveur. Vous pouvez consigner les détails de l'exception dans les méthodes SyncProcessMessage, ProcessMessage ou SyncProcessMessage si une exception se produit. Les paramètres IMessage et Exception fournissent les détails de l'exception.
Audit et journalisation
Si vous utilisez l'hôte ASP.NET, vous pouvez utiliser les fonctionnalités d'audit d'IIS. Si vous utilisez un hôte personnalisé, implémentez un audit personnalisé. Pour ce faire, vous pouvez implémenter un récepteur de canal personnalisé.
Utilisation d'un récepteur de canal personnalisé
Vous pouvez implémenter un récepteur de canal personnalisé pour exécuter l'audit côté client et/ou côté serveur. Vous pouvez obtenir les détails grâce aux méthodes SyncProcessMessage, ProcessMessage ou SyncProcessMessage.
Considérations sur la sécurité d'accès au code (CAS)
Les clients distants exigent une confiance totale sur les versions 1.0 et 1.1 de .NET Framework. L'assembly System.Runtime.Remoting.dll n'est pas marqué avec AllowPartiallyTrustedCallersAttribute.
Si vous souhaitez utiliser l'accès distant pour appeler un composant distant à partir d'un code de confiance partielle (comme une application Web de confiance partielle), vous devez créer un assembly de wrappers de confiance totale et mettre en sandbox les appels de méthode de l'objet distant. Pour plus d'informations sur la mise en sandbox de code et l'utilisation d'assemblys de wrappers, reportez-vous au module 9, « Utilisation de la sécurité d'accès au code avec ASP.NET ».
Résumé
L'infrastructure d'accès distant .NET Framework est conçue pour être utilisée avec des serveurs sécurisés, où il est possible de limiter les appelants aux clients de confiance, par exemple en utilisant des stratégies de sécurité IPSec. Si vous utilisez un hôte ASP.NET et HttpChannel, vous pouvez profiter des fonctionnalités de sécurité sous-jacentes fournies par ASP.NET et IIS. Si vous utilisez un hôte personnalisé et TcpChannel, peut-être pour des questions de performances, vous devez implémenter vos propres solutions d'authentification et d'autorisation. IPSec peut être utile dans ce type de situation parce qu'il sécurise les communications et offre une authentification au niveau de la machine.
Informations complémentaires
Pour plus d'informations, reportez-vous aux ressources suivantes :
-
Si vous souhaitez une liste de contrôle imprimable, veuillez consulter la « Liste de contrôle : sécurisation de l'accès distant » dans la section « Listes de contrôle » de ce guide.
-
Pour plus d'informations sur la façon d'héberger un composant distant dans un service Windows, reportez-vous à la rubrique « How To: Host a Remote Object in a Windows Service » dans la section « How To » de « Microsoft patterns & practices Volume I, Building Secure ASP.NET Web Applications: Authentication, Authorization, and Secure Communication » à l'adresse suivante : http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT15.asp.
-
Pour plus d'informations sur la façon de créer une solution d'authentification personnalisée utilisant SSPI, reportez-vous à l'article de MSDN « .NET Remoting Security Solution, Part 1: Microsoft.Samples.Security.SSPI Assembly », à l'adresse suivante : http://msdn.microsoft.com/library/en-us/dndotnet/html/remsspi.asp.
Remarque : l'implémentation présentée dans cet article est un exemple et non un produit testé ni pris en charge par Microsoft.