检查asp.net mvc 4应用程序中的ssl协议,密码和其他属性

由于合规性原因,我们必须在我们的网络服务器上关闭一些密码和SSL2的支持。 这不是一个真正的问题,但我们也想在他们成功登录网站后通知他们,我们建议在他们尚未使用TLS 1.2连接到服务器的情况下在他们的浏览器中启用TLS 1.2。 所以我的问题是:

如何检测https请求中使用的协议和密码到IIS中运行的ASP.net(MVC 4)应用程序?

我知道有办法将SCHANNEL请求记录到事件日志中,然后再次将它们读出来,但这对我来说听起来非常难看。

我已经看到System.Net.Security.SslStream具有我需要的属性,例如: CipherAlgorithm,HashAlgorithm,KeyExchangeAlgorithm和SslProtocol ,但我不知道在mvc4中我可以在我的Controller Action中获取这些属性的位置应用。

由ILSpy确定的坏消息是,无法从ASP.NET内的任何地方访问System.Net.SslStream实例。 该类用于针对网络的直接编程,例如通过WCF框架。 从ASP.NET(无论是在IIS还是HttpListener上使用System.Web或OWIN)可以做的最好的事情是获取服务器变量( 请参阅IIS服务器变量列表 ),了解连接是否受到协商的任何安全传输的保护与客户。

至于在Web请求期间确定性地从事件日志中读取数据……这看起来很可怕。 但如果你可以使它工作,请分享代码。 🙂

或者,您可以尝试使用下面使用SslStream您自己的Owin主机(也称为Web服务器!)。 也许。 :P有关SslStream编程的详细介绍,请参阅此文章 。

但是,由于您已经能够关闭服务器上的某些协议(如本文所述 ,我假设)…您可以在两个不同的子域上设置您的站点,例如www.example.comsecure.example.com ,前者是一个vanilla Web服务器,后者配置为只接受TLS 1.2连接。 然后,您将编写一些从www.example.com提供的引导逻辑,并尝试向secure.example.com/securityUpgradeCheck发出AJAX请求(可能使用风格很好的微调动画和“请等待,尝试保护此连接“文字打动你的用户:))。 如果该请求成功,则可以将用户重定向到secure.example.com (可能是永久性的,因为已知该用户代理支持TLS 1.2,除非由于某种原因用户更改其浏览器设置)。

为了增加影响,请为安全域订购EV SSL证书,以便用户注意安全性升级。 🙂

更新:我在编写自定义(本机)ISAPIfilter(或扩展)的理论基础上进行了一些挖掘,以通过SChannel API获取此信息。 起初我很有希望,因为我发现了一个函数HSE_REQ_GET_SSPI_INFO ,它将返回一个SSPI CtxtHandle结构,你可以通过EXTENSION_CONTROL_BLOCK ServerSupportFunction函数从一个自定义ISAPI扩展调用它。 事实certificate, CtxtHandle结构代表一个SChannel上下文, 可以为您提供对SECPKG_ATTR_CONNECTION_INFO属性的引用,您可以使用该属性检索SSL连接级别信息(与.NET中的SslStream类中显示的信息相同,就我而言可以说)。 然而,遗憾的是, 微软预计这种可能性并决定只有在使用客户端证书时才能获得此信息。 行为是“按设计”。

有一个(本机)SSPI函数, QueryContextAttributes (Schannel) ,我在通过MSDN进行的长期搜索中发现它可能有效。 我没有尝试过,它可能因为与上面链接的ISAPI API限制相同的“按设计”原因而失败。 但是,它可能值得一试。 如果您想探索此路由,以下是ISAPI扩展的示例 。 实际上,使用这种方法,您可以使用较新的IIS 7.0+ SDK编写IIS模块。

但是,假设您没有要求客户端证书的奢侈品,并且远射不起作用,那绝对只留下两个选项。

  1. 使用不同的Web服务器(Apache等),在同一物理/虚拟机上运行但在不同的端口上运行等(根据我们在评论中的讨论,因为您无法启动另一台机器)。 如果您只想给客户端提供信息性消息,那么这种方法与AJAX请求相结合可能就足够了。 是的,一个不同的端口很可能被某个地方的防火墙阻止,但是嘿 – 它只是一个可选的信息性消息。
  2. 依靠System事件日志的半脆性方法。 启用S​​channel事件日志记录 ,然后编写一些事件日志查询代码,尝试将请求与上次记录的Schannel事件相关联。 请注意,您需要找到一种方法来可靠地将事件日志中放入的内容与当前HTTP请求相关联,因此在这种情况下您可能还需要编写ISAPIfilter/扩展或IIS模块以查找Schannel上下文句柄(这是我假设相关性将基于)。

顺便说一句 – 您的负载均衡器是否配置为执行任何SSL拦截? 因为那时候整个事情都没有实际意义……只是想一想。

更新:启用S​​channel日志记录净化此gem:

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

这可以直接从托管代码中读取。 我认为UserID仅对应于IIS工作进程SID,但假设您可以提出某种相关启发式,您可以设置后台线程来连续轮询事件日志并为您提供最近建立的客户端列表握手(或许使用ConcurrentDictionary )。

那里。 而已。 没有更好奇的调查我。 我受够了。 :P

感兴趣地读这个,因为我们有完全相同的问题。

在我看来,必须有一个公共Web服务可用于查询此类信息,我做了一些研究,发现了这个: https : //www.howsmyssl.com/s/api.html

API就在这里

可以从客户端Javascript调用此API,它返回标准JSON,可以轻松解析并向用户显示合适的警报。

您还可以将信息发送到您自己的Web服务以进行日志记录,并尝试将信息与现有的IIS日志结合使用。

您面临的唯一问题是依赖第三方。 这可以通过站起来自己的服务器并托管GitHub上免费提供的代码来缓解。

我们将开始研究这个解决方案,所以一旦我有一些代码,我将更新这个答案。

再次感谢Lars的上述综合答案。 我会将此作为对该post的评论添加,但我认为值得创建一个单独的答案,以便人们可以更容易地找到它。