Подтвердить что ты не робот

Проверьте протокол ssl, шифр и другие свойства в приложении asp.net mvc 4

Из-за требований соблюдения мы должны отключить поддержку некоторых шифров и SSL2 на наших веб-серверах. Это не проблема, но мы также хотели бы сообщить им после успешного входа на сайт, что мы предлагаем включить TLS 1.2 в своем браузере, если они еще не подключены к серверу с TLS 1.2. Поэтому у меня есть вопрос:

Как определить протокол и шифр, используемые в запросе https для приложения ASP.net(MVC 4), работающего в IIS?

Я знаю, что есть способы зарегистрировать запрос SCHANNEL в журнале событий, а затем снова прочитать их, но это звучит очень уродливо для меня.

И я видел, что System.Net.Security.SslStream имеет необходимые мне свойства, например: CipherAlgorithm, HashAlgorithm, KeyExchangeAlgorithm и SslProtocol, но я не уверен, где могу получить эти свойства в моем действии Controller в приложении mvc4.

4b9b3361

Ответ 1

Плохая новость, определенная ILSpy, заключается в том, что нет способа получить System.Net.SslStream экземпляру System.Net.SslStream из любой части ASP.NET. Этот класс используется для прямого программирования в сети, например, инфраструктурой WCF. Лучшее, что вы можете сделать из ASP.NET (будь то использование System.Web или OWIN поверх IIS или HttpListener), - это получить серверную переменную (см. Список серверных переменных IIS) для определения того, защищено ли соединение каким-либо безопасным транспортом, о котором было согласовано. с клиентом.

Что касается детерминированного чтения данных из журнала событий во время веб-запроса... это кажется пугающим. Но если вы можете заставить его работать, поделитесь кодом. :)

В качестве альтернативы, вы можете попробовать реализовать свой собственный хост Owin (он же веб-сервер!), SslStream использует SslStream. Может быть. : P Смотрите эту статью для полного знакомства с программированием SslStream.

Но так как вы уже можете отключить определенные протоколы на своем сервере (как в этой статье, я полагаю)... Вы можете настроить свой сайт на двух разных поддоменах, например, www.example.com и secure.example.com где первый является ванильным веб-сервером, а последний настроен на прием только соединений TLS 1.2. Затем вы должны написать некоторую логику начальной загрузки, которая secure.example.com/securityUpgradeCheck с secure.example.com/securityUpgradeCheck www.example.com и secure.example.com/securityUpgradeCheck сделать AJAX-запрос к secure.example.com/securityUpgradeCheck (возможно, с красиво оформленной вращающейся анимацией и "Пожалуйста, подождите, пытаясь защитить это соединение"). текст, чтобы произвести впечатление на ваших пользователей :)). Если этот запрос выполнен успешно, пользователь может быть перенаправлен на secure.example.com (возможно, навсегда, поскольку этот пользовательский агент, как тогда известно, поддерживает TLS 1.2, если только по какой-то причине пользователь не изменит свои настройки браузера).

Для дополнительного эффекта закажите сертификат EV SSL для защищенного домена, чтобы ваши пользователи заметили обновление в безопасности. :)

ОБНОВЛЕНИЕ: я сделал еще несколько копаний на теоретической основе написания собственного (собственного) фильтра (или расширения) ISAPI, чтобы получить эту информацию через SChannel API. Сначала я надеялся, что обнаружил функцию HSE_REQ_GET_SSPI_INFO которая будет возвращать структуру SSPI CtxtHandle и которую можно вызывать из пользовательского расширения ISAPI через функцию EXTENSION_CONTROL_BLOCK ServerSupportFunction. CtxtHandle структура CtxtHandle представляет контекст SChannel и может дать вам ссылку на атрибут SECPKG_ATTR_CONNECTION_INFO с помощью которого вы можете получить информацию об уровне соединения SSL (ту же информацию, которая появилась в классе SslStream в .NET, насколько я мог бы сказать). Однако, к сожалению, Microsoft предвидела такую возможность и решила, что эта информация доступна, только если вы используете клиентские сертификаты. Поведение "по замыслу".

Была одна (нативная) функция SSPI, QueryContextAttributes (Schannel), которую я обнаружил во время долгой охоты через MSDN, которая может работать. Я не пробовал его, и он мог просто потерпеть неудачу по той же самой "конструктивной" причине, что и ограничение ISAPI API, упомянутое выше. Однако стоит попробовать. Если вы хотите изучить этот маршрут, вот пример расширения ISAPI. На самом деле, при таком подходе вы могли бы вместо этого написать модуль IIS, используя более новый IIS 7. 0+ SDK.

Но если предположить, что вы не можете позволить себе роскошь требовать клиентские сертификаты и этот длинный выстрел не сработает, то это абсолютно оставляет только два варианта.

  1. Используйте другой веб-сервер (Apache и т.д.), Работающий на той же физической/виртуальной машине, но на другом порту и т.д. (Согласно нашему обсуждению в комментариях, поскольку вы не можете раскрутить другую машину). Если вы хотите передать клиенту только информационное сообщение, то такого подхода в сочетании с запросом AJAX может быть достаточно. Да, другой порт может быть где-то заблокирован брандмауэром, но в любом случае - это всего лишь необязательное информационное сообщение.
  2. Положитесь на полукрупкий подход с журналом системных событий. Включите ведение журнала событий Schannel, а затем напишите некоторый код запроса журнала событий, чтобы попытаться соотнести запрос с последним зарегистрированным событием Schannel. Обратите внимание, что вам нужно найти способ надежно соотнести все, что помещается в журнал событий, с текущим HTTP-запросом, поэтому вам может также понадобиться написать фильтр/расширение ISAPI или модуль IIS в этом случае, чтобы найти дескриптор контекста Schannel. (что я предполагаю, что корреляция будет основана на)

Кстати, настроен ли ваш балансировщик нагрузки на перехват SSL? Потому что тогда все это дело спорно так или иначе... Только мысль, чтобы рассмотреть.

ОБНОВЛЕНИЕ: Включение регистрации Schannel собрало этот драгоценный камень:

<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>

Это можно прочитать прямо из управляемого кода. Я думаю, что UserID соответствует только SID рабочего процесса IIS, к сожалению, но при условии, что вы можете придумать какую-то корреляционную эвристику, вы можете настроить фоновый поток для постоянного опроса журнала событий и предоставления вам списка недавно установленных клиентов. рукопожатия (возможно, используйте ConcurrentDictionary).

Там. Это. Нет больше любопытного расследования для меня. Я задолбался. :П

Ответ 2

Читать это с интересом, так как у нас точно такая же проблема.

Мне пришло в голову, что должен быть общедоступный веб-сервис, доступный для запроса информации такого типа, и я провел небольшое исследование и обнаружил это: https://www.howsmyssl.com/s/api.html

API здесь

Этот API может вызываться из клиентского Javascript, и он возвращает стандартный JSON, который может быть легко проанализирован, и подходящее оповещение показывается вашим пользователям.

Вы также можете отправить информацию в свой собственный веб-сервис для целей регистрации и попытаться объединить информацию с существующими журналами IIS.

Единственная проблема, с которой вы сталкиваетесь, - это полагаться на третьих лиц. Этого можно избежать, подняв собственный сервер и разместив код, который свободно доступен на GitHub.

Мы будем работать над этим решением, поэтому, как только у меня появится код, я обновлю этот ответ.

Еще раз спасибо Ларсу за исчерпывающий ответ выше. Я бы добавил это в качестве комментария к этому сообщению, однако я подумал, что стоит создать отдельный ответ, чтобы людям было легче его найти.