web-dev-qa-db-fra.com

Vérifiez le protocole SSL, le chiffrement et d'autres propriétés dans une application asp.net mvc 4

Pour des raisons de conformité, nous devons désactiver la prise en charge de certains chiffrements et de SSL2 sur nos serveurs Web. Ce n'est pas vraiment un problème, mais nous souhaitons également les informer, après leur connexion réussie au site Web, que nous suggérons d'activer TLS 1.2 dans leur navigateur s'ils ne se connectent pas déjà au serveur avec TLS 1.2. Donc la question que j'ai est:

Comment puis-je détecter le protocole et le chiffrement utilisés dans une demande https à une application ASP.net (MVC 4) s'exécutant dans IIS?

Je sais qu'il existe des moyens de consigner la demande SCHANNEL dans le journal des événements, puis de la relire à nouveau, mais cela me semble très moche.

Et j'ai vu que le System.Net.Security.SslStream a les propriétés dont j'aurais besoin, par exemple: CipherAlgorithm, HashAlgorithm, KeyExchangeAlgorithm & SslProtocol, mais je ne sais pas où je peux les obtenir propriétés dans mon action de contrôleur dans une application mvc4.

26
Chief Wiggum

La mauvaise nouvelle, telle que déterminée par ILSpy _, est qu'il n'y a aucun moyen de se rendre à une instance System.Net.SslStream à partir de n'importe où dans ASP.NET. Cette classe est utilisée pour la programmation directe sur le réseau, par exemple via la structure WCF. Le mieux que vous puissiez faire avec ASP.NET (que vous utilisiez System.Web ou OWIN en plus de IIS ou de HttpListener) consiste à obtenir une variable de serveur ( voir la liste des variables de serveur IIS) }. _) pour déterminer si la connexion est sécurisée par le moyen de transport sécurisé négocié avec le client.

En ce qui concerne la lecture déterministe des données du journal des événements lors d'une requête Web ... cela semble effrayant. Mais si vous pouvez le faire fonctionner, veuillez partager le code. :)

Vous pouvez également essayer de mettre en œuvre votre propre hôte Owin (également appelé serveur Web!) Qui utilise SslStream en dessous. Peut être. : P Voir cet article _ pour une introduction complète à la programmation SslStream.

Mais comme vous êtes déjà en mesure de désactiver certains protocoles sur votre serveur (comme dans cet article , je suppose) ... vous pouvez configurer votre site sur deux sous-domaines différents, par exemple. www.example.com et secure.example.com, où le premier est un serveur Web Vanilla et le dernier est configuré pour accepter uniquement les connexions TLS 1.2. Ensuite, vous écririez une logique d'amorçage qui serait servie à partir de www.example.com et tenteriez d'envoyer une demande AJAX à secure.example.com/securityUpgradeCheck (éventuellement avec une animation spinner bien stylée et le texte "Veuillez patienter, tentant de sécuriser cette connexion" pour impressionner vos utilisateurs. :)). Si cette demande aboutit, l'utilisateur peut être redirigé vers secure.example.com (probablement en permanence, car il est alors reconnu que cet agent utilisateur prend en charge TLS 1.2, sauf si, pour une raison quelconque, l'utilisateur modifie les paramètres de son navigateur).

Pour un impact accru, commandez un certificat SSL EV pour le domaine sécurisé afin que vos utilisateurs remarquent la mise à niveau de la sécurité. :)

UPDATE: J'ai approfondi mes connaissances en écrivant un filtre ISAPI personnalisé (natif) (ou une extension) pour obtenir ces informations via l'API SChannel. Au début, j'avais bon espoir car j'avais découvert une fonction HSE_REQ_GET_SSPI_INFO qui renverrait une structure SSPI CtxtHandle et que vous pourriez appeler à partir d'une extension ISAPI personnalisée via la fonction EXTENSION_CONTROL_BLOCKServerSupportFunction. Il s'avère que cette structure CtxtHandle représente un contexte SChannel et que peut vous fournir une référence à un attribut SECPKG_ATTR_CONNECTION_INFO avec lequel vous pouvez extraire des informations de niveau de connexion SSL (les mêmes informations que celles présentées dans la classe SslStream dans .NET, pour autant que je puisse dire). Malheureusement, Microsoft a anticipé cette possibilité et a décidé que ces informations ne sont disponibles que si vous utilisez des certificats clients. Le comportement est "par conception".

Il y avait une fonction SSPI (native), QueryContextAttributes (Schannel) , que j'ai découverte au cours d'une longue recherche dans MSDN et qui pouvait fonctionner. Je ne l'ai pas essayé et il pourrait tout simplement échouer pour la même raison «de conception» que la limitation de l'API ISAPI liée à ci-dessus. Cependant, cela vaut peut-être la peine d'essayer. Si vous souhaitez explorer cet itinéraire, voici un exemple d'extension ISAPI . En fait, avec cette approche, vous pourriez peut-être écrire un module IIS à la place, en utilisant le nouveau IIS 7.0+ SDK.

Mais si vous n’avez pas le luxe d’exiger des certificats de client et que le plan à long terme ne fonctionne pas, il ne vous reste que deux options.

  1. Utilisez un autre serveur Web (Apache, etc.) fonctionnant sur le même ordinateur physique/virtuel, mais sur un port différent, etc. (conformément à notre discussion dans les commentaires, car vous ne pouvez pas démarrer un autre ordinateur). Si vous souhaitez uniquement envoyer un message d’information au client, cette approche, associée à une requête AJAX, peut suffire. Oui, un pare-feu pourrait bloquer un port différent quelque part, mais bon, c’est de toute façon un message d’information facultatif.
  2. Utilisez l’approche semi-fragile avec le journal des événements système. Activer la journalisation des événements Schannel puis écrivez un code d'interrogation du journal des événements pour tenter de corréler la demande avec l'événement Schannel consigné en dernier. Notez que vous aurez besoin de trouver un moyen de corréler de manière fiable tout ce qui sera mis dans le journal des événements avec la requête HTTP en cours, de sorte que vous pourriez également avoir besoin d'écrire un filtre/extension ISAPI ou un module IIS dans Dans ce cas, recherchez le descripteur de contexte Schannel (ce sur quoi je suppose que la corrélation serait basée).

Soit dit en passant, votre équilibreur de charge est-il configuré pour effectuer une interception SSL? Parce qu'alors tout cela est discutable de toute façon ... Juste une pensée à considérer.

UPDATE: L'activation de la journalisation Schannel a généré cette gemme:

<Event xmlns="http://schemas.Microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Schannel" Guid="{1F678132-5938-4686-9FDC-C8FF68F15C85}" /> 
    <EventID>36880</EventID> 
    <Version>0</Version> 
    <Level>4</Level> 
    <Task>0</Task> 
    <Opcode>0</Opcode> 
    <Keywords>0x8000000000000000</Keywords> 
    <TimeCreated SystemTime="2014-08-13T02:59:35.431187600Z" /> 
    <EventRecordID>25943</EventRecordID> 
    <Correlation /> 
    <Execution ProcessID="928" ThreadID="12912" /> 
    <Channel>System</Channel> 
    <Computer>**********</Computer> 
    <Security UserID="S-1-5-18" /> 
  </System>
  <UserData>
    <EventXML xmlns:auto-ns3="http://schemas.Microsoft.com/win/2004/08/events" xmlns="LSA_NS">
      <Type>client</Type> 
      <Protocol>TLS 1.2</Protocol> 
      <CipherSuite>0x3c</CipherSuite> 
      <ExchangeStrength>2048</ExchangeStrength> 
    </EventXML>
  </UserData>
</Event>

Cela peut être lu directement à partir du code géré. Je pense que l'ID utilisateur correspond uniquement au SID du processus de travail IIS, malheureusement, mais en supposant que vous puissiez créer une sorte d'heuristique de corrélation, vous pouvez configurer un thread d'arrière-plan pour interroger en permanence le journal des événements et vous fournir une liste. des poignées de main de clients récemment établies (utilisez un ConcurrentDictionary peut-être).

Là. C'est tout. Pas plus curieux d'investigation pour moi. J'ai fini. : P

33
Lars Kemmann

En lisant cela avec intérêt, nous avons exactement le même problème.

Je me suis rendu compte qu’il devait exister un service Web public pour interroger ce type d’informations. J’ai fait une petite recherche et trouvé ceci: https://www.howsmyssl.com/s/api.html

L'API est ici

Cette API peut être appelée à partir de Javascript côté client. Elle retourne un JSON standard qui peut être facilement analysé et une alerte appropriée présentée à vos utilisateurs. 

Vous pouvez également envoyer les informations à votre propre service Web à des fins de journalisation et essayer de les combiner avec vos journaux IIS existants.

Le seul problème auquel vous êtes confrontés à l’époque est de faire appel à une tierce partie. Cela peut être atténué en mettant votre propre serveur en service et en hébergeant le code disponible gratuitement sur GitHub .

Nous allons travailler sur cette solution, donc une fois le code en place, je mettrai à jour cette réponse.

Merci encore à Lars pour la réponse complète ci-dessus. J'aurais ajouté ceci comme commentaire à ce billet, mais j’ai pensé que cela valait la peine de créer une réponse distincte pour que les gens puissent le trouver plus facilement.

5
CarlR

Comment vérifiez-vous la négociation TLS négociée à partir du serveur? a le moyen d'obtenir cela sous IIS 8.5 et versions ultérieures dans ASP.Net MVC/WebAPI. Au moins, cela a fonctionné pour moi et quelques autres quand j'ai répondu hier.

0