Compruebe el protocolo ssl, el cifrado y otras propiedades en una aplicación asp.net mvc 4

Debido a razones de cumplimiento, debemos desactivar el soporte de algunos cifrados y SSL2 en nuestros servidores web. Esto no es realmente un problema, pero también nos gustaría informarles, después de su exitoso inicio de sesión en el sitio web, que sugerimos activar TLS 1.2 en su navegador en caso de que todavía no se estén conectando al servidor con TLS 1.2. Entonces la pregunta que tengo es:

¿Cómo puedo detectar el protocolo y el cifrado utilizados en una solicitud https a una aplicación ASP.net (MVC 4) que se ejecuta en IIS?

Sé que hay formas de registrar la solicitud de SCHANNEL en el registro de eventos y luego volver a leerlos, pero esto me parece muy feo.

Y he visto que System.Net.Security.SslStream tiene las propiedades que necesitaría, por ejemplo: CipherAlgorithm, HashAlgorithm, KeyExchangeAlgorithm y SslProtocol , pero no estoy seguro de dónde puedo obtener estas propiedades en mi Controller Action en un mvc4 solicitud.

Las malas noticias, como lo determina ILSpy , es que no hay forma de acceder a una instancia de System.Net.SslStream desde cualquier lugar dentro de ASP.NET. Esa clase se usa para progtwigción directa contra la red, por ejemplo, por el marco WCF. Lo mejor que puede hacer desde ASP.NET (ya sea utilizando System.Web u OWIN en la parte superior de IIS o HttpListener) es obtener una variable de servidor ( consulte la lista de variables de servidor de IIS ) para saber si la conexión está asegurada por el transporte seguro negociado. con el cliente.

En cuanto a la lectura determinista de los datos del registro de eventos durante una solicitud web … eso parece aterrador. Pero si puede hacer que funcione, comparta el código. 🙂

Alternativamente, podrías intentar implementar tu propio host Owin (también conocido como servidor web) que usa SslStream debajo. Tal vez. : P Vea este artículo para una introducción completa a la progtwigción de SslStream .

Pero dado que ya puede desactivar ciertos protocolos en su servidor (como en este artículo , supongo) … Podría configurar su sitio en dos subdominios diferentes, por ejemplo, www.example.com y secure.example.com , donde el primero es un servidor web vainilla y el último está configurado para aceptar únicamente conexiones TLS 1.2. Luego, escribiría una cierta lógica de arranque que se sirve desde www.example.com e intentará hacer una solicitud de AJAX para secure.example.com/securityUpgradeCheck (posiblemente con una animación spinner muy bien diseñada y “Espere, intente proteger esta conexión” “texto para impresionar a tus usuarios :)). Si la solicitud tiene éxito, el usuario puede ser redireccionado a secure.example.com (probablemente de forma permanente, ya que se sabe que ese agente de usuario admite TLS 1.2 a menos que por alguna razón el usuario cambie la configuración de su navegador).

Para un impacto adicional, solicite un certificado EV SSL para el dominio seguro para que sus usuarios noten la actualización en seguridad. 🙂

ACTUALIZACIÓN: Hice un poco más de excavación, sobre la base teórica de escribir un filtro (o extensión) ISAPI personalizado (nativo) para obtener esta información a través de la API de SChannel. Al principio tenía esperanzas porque descubrí una función HSE_REQ_GET_SSPI_INFO que devolvería una estructura SSPI CtxtHandle , y que podría llamar desde una extensión ISAPI personalizada a través de la función EXTENSION_CONTROL_BLOCK ServerSupportFunction . CtxtHandle que CtxtHandle estructura CtxtHandle representa un contexto de SChannel y puede hacerte una referencia a un atributo SECPKG_ATTR_CONNECTION_INFO con el que puedes recuperar información de nivel de conexión SSL (la misma información que apareció en la clase SslStream en .NET, en la medida en que podría decir). Sin embargo, lamentablemente, Microsoft anticipó esa posibilidad y decidió que esta información solo está disponible si está utilizando certificados de clientes. El comportamiento es “por diseño”.

Hubo una función SSPI (nativa), QueryContextAttributes (Schannel) , que descubrí durante una larga búsqueda a través de MSDN, que puede funcionar. No lo he probado, y simplemente podría fallar por la misma razón “por diseño” que la limitación de la API ISAPI vinculada anteriormente. Sin embargo, puede valer la pena intentarlo. Si desea explorar esta ruta, aquí hay un ejemplo de una extensión ISAPI . En realidad, con este enfoque, es posible que pueda escribir un módulo IIS en su lugar, utilizando el último SDK de IIS 7.0+.

Pero, suponiendo que no tenga el lujo de requerir certificados del cliente y que la oportunidad no funciona, eso solo deja dos opciones.

  1. Use un servidor web diferente (Apache, etc.), que se ejecute en la misma máquina física / virtual pero en un puerto diferente, etc. (según nuestra discusión en los comentarios, ya que no puede hacer girar otra máquina). Si solo desea darle al cliente un mensaje informativo, entonces este enfoque, junto con una solicitud de AJAX, podría ser suficiente. Sí, un puerto diferente podría estar bloqueado por un firewall en alguna parte, pero bueno, de todos modos es solo un mensaje informativo opcional.
  2. Confíe en el enfoque semi-frágil con el registro de eventos del sistema. Habilite el registro de eventos de Schannel y luego escriba algún código de consulta de registro de eventos para intentar correlacionar la solicitud con el último evento de Schannel registrado. Tenga en cuenta que deberá encontrar una forma de correlacionar de manera confiable lo que se coloca en el registro de eventos con la solicitud HTTP actual, por lo que también podría necesitar escribir un filtro / extensión ISAPI o módulo IIS en este caso para encontrar el contexto de Schannel. (que es en lo que supongo que se basaría la correlación).

Por cierto, ¿está configurado su equilibrador de carga para realizar cualquier intercepción de SSL? Porque entonces todo esto es discutible de todos modos … Solo un pensamiento para considerar.

ACTUALIZACIÓN: Habilitar el registro de Schannel generó esta gem:

    36880 0 4 0 0 0x8000000000000000  25943   System **********     client TLS 1.2 0x3c 2048    

Esto se puede leer directamente desde el código administrado. Creo que el ID de usuario solo corresponde al SID del proceso de trabajo de IIS, desafortunadamente, pero suponiendo que se pueda encontrar algún tipo de heurística de correlación, puede configurar un hilo de fondo para sondear continuamente el registro de eventos y darle una lista de clientes recientemente establecidos apretones de manos (use un ConcurrentDictionary tal vez).

Ahí. Eso es. No más curioso investigando para mí. He terminado. :PAG

Leyendo esto con interés ya que tenemos exactamente el mismo problema.

Se me ocurrió que debe haber un servicio web público disponible para consultar este tipo de información e investigué un poco y encontré esto: https://www.howsmyssl.com/s/api.html

La API está aquí

Esta API se puede llamar desde el lado del cliente de Javascript y devuelve JSON estándar que se puede analizar fácilmente y se puede mostrar una alerta adecuada a los usuarios.

También puede enviar la información a su propio servicio web para fines de registro e intentar combinar la información con sus registros de IIS existentes.

El único problema al que se enfrenta es confiar en un tercero. Esto puede mitigarse poniendo de pie su propio servidor y alojando el código que está disponible gratuitamente en GitHub .

Vamos a trabajar en esta solución, así que una vez que tenga algún código, actualizaré esta respuesta.

Gracias de nuevo a Lars por la respuesta integral anterior. Hubiera agregado esto como un comentario a esa publicación; sin embargo, pensé que valía la pena crear una respuesta por separado para que la gente lo encuentre más fácil.