如何在.NET中禁用SSL回退并仅使用TLS进行出站连接?(贵宾犬缓解)

Jor*_*ger 103 .net ssl

我正在努力减轻我们对Poodle SSL 3.0 Fallback攻击的漏洞.我们的管理员已经开始禁用SSL,转而使用TLS进行服务器的入站连接.我们还建议我们的团队在其Web浏览器中禁用SSL.我现在正在查看我们的.NET代码库,它通过System.Net.HttpWebRequest启动与各种服务的HTTPS连接.我相信如果这些连接允许从TLS回退到SSL,则它们可能容易受到MITM攻击.这是我到目前为止所确定的.有人可以仔细检查一下以确认我是对的吗?这个漏洞是全新的,所以我还没有看到微软如何在.NET中缓解它的任何指导:

  1. System.Net.Security.SslStream类的允许协议(支持.NET中的安全通信)通过System.Net.ServicePointManager.SecurityProtocol属性为每个AppDomain全局设置.

  2. .NET 4.5中此属性的默认值是Ssl3 | Tls(虽然我找不到支持它的文档.)SecurityProtocolType是带有Flags属性的枚举,因此它是这两个值的按位OR.您可以使用以下代码行在您的环境中进行检查:

    Console.WriteLine(System.Net.ServicePointManager.SecurityProtocol.ToString());

  3. 在应用程序中启动任何连接之前Tls,应该将其更改为正好或者可能Tls12:

    System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls;

  4. 重要提示:由于该属性支持多个按位标志,因此我假设SslStream 在握手期间不会自动回退到其他未指定的协议.否则,支持多个标志会有什么意义?

TLS 1.0与1.1/1.2的更新:

根据Google安全专家Adam Langley的说法,如果没有正确实施,TLS 1.0后来被发现容易受到POODLE的影响,因此您应该考虑专门转移到TLS 1.2.

Edd*_*fen 134

我们正在做同样的事情.要仅支持TLS 1.2且不支持SSL协议,您可以执行以下操作:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Run Code Online (Sandbox Code Playgroud)

SecurityProtocolType.Tls仅为TLS 1.0,并非所有TLS版本.

作为一方:如果你想检查你的网站是否允许SSL连接,你可以在这里这样做(我不认为这会受到上述设置的影响,我们不得不编辑注册表以强制IIS使用TLS传入连接):https: //www.ssllabs.com/ssltest/index.html

要在IIS中禁用SSL 2.0和3.0,请参阅此页面:https://www.sslshopper.com/article-how-to-disable-ssl-2.0-in-iis-7.html

  • 注意:看起来`SecurityProtocolType.Tls11`和`SecurityProtocolType.Tls12`枚举值仅在ASP.net 4.5及更高版本中可用.如果TLS 1.0被淘汰,我们不确定在2.0上运行的旧代码库需要做些什么. (7认同)
  • @ScotterMonkey如果要从.NET代码启动*outbound*连接,例如从服务器上运行的自定义代码连接到Web服务或API,则只需设置System.Net.ServicePointManager.SecurityProtocol.如果您只运行一个简单的网站,并且您只接受来自浏览器的*传入*连接,那么注册表修复就足够了. (4认同)

Pro*_*gle 23

@Eddie Loeffen的答案似乎是这个问题最受欢迎的答案,但它有一些不良的长期影响.如果你在这里查看System.Net.ServicePointManager.SecurityProtocol的文档页面,那么备注部分意味着协商阶段应该只解决这个问题(强制协议是不好的做法,因为将来TLS 1.2也会受到影响).但是,如果有的话,我们不会寻找这个答案.

研究表明,ALPN协商协议在协商阶段需要到达TLS1.2.我们以此为出发点,尝试了.Net框架的新版本,以了解支持的起点.我们发现.Net 4.5.2不支持与TLS 1.2协商,但.Net 4.6确实如此.

因此,即使强制TLS1.2现在可以完成工作,我建议您升级到.Net 4.6.由于这是2016年6月的PCI DSS问题,因此窗口很短,但新框架是一个更好的答案.

更新:根据评论,我建立了这个:

ServicePointManager.SecurityProtocol = 0;    
foreach (SecurityProtocolType protocol in SecurityProtocolType.GetValues(typeof(SecurityProtocolType)))
    {
        switch (protocol)
        {
            case SecurityProtocolType.Ssl3:
            case SecurityProtocolType.Tls:
            case SecurityProtocolType.Tls11:
                break;
            default:
                ServicePointManager.SecurityProtocol |= protocol;
            break;
        }
    }
Run Code Online (Sandbox Code Playgroud)

为了验证这个概念,我或者将SSL3和TLS1.2放在一起,并运行针对仅支持TLS 1.0和TLS 1.2(1.1被禁用)的服务器的代码.使用or'd协议,似乎连接正常.如果我更改为SSL3和TLS 1.1,则无法连接.我的验证使用来自System.Net的HttpWebRequest,只调用GetResponse().例如,我试过这个并且失败了:

        HttpWebRequest request = WebRequest.Create("https://www.contoso.com/my/web/resource") as HttpWebRequest;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls11;
        request.GetResponse();
Run Code Online (Sandbox Code Playgroud)

虽然这有效:

        HttpWebRequest request = WebRequest.Create("https://www.contoso.com/my/web/resource") as HttpWebRequest;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
        request.GetResponse();
Run Code Online (Sandbox Code Playgroud)

这比强制TLS 1.2有一个优势,如果.Net框架升级,以便Enum中有更多条目,代码将支持它们.它仅仅使用.Net 4.6有一个缺点,即4.6使用ALPN并且如果没有指定限制则应该支持新协议.

  • 有没有其他人发现.NET不能自动协商它能够达到的最高协议版本? (7认同)
  • 有趣.看起来文档页面随着MSDN的更新而移动到".NET Framework**(当前版本)**",现在解释为"此目的没有为此属性列出默认值".也许接受答案的更具未来性的版本是首先查询属性以检索允许的协议列表,然后删除应用程序认为不安全的协议(即任何小于TLS 1.2的内容),而不是仅显式添加那些你认为安全的.这不会排除将来的新版本. (3认同)

CZa*_*sky 7

我不得不转换等效的整数来绕过我仍在使用 .NET 4.0 的事实

System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
/* Note the property type  
   [System.Flags]
   public enum SecurityProtocolType
   {
     Ssl3 = 48,
     Tls = 192,
     Tls11 = 768,
     Tls12 = 3072,
   } 
*/
Run Code Online (Sandbox Code Playgroud)

  • 有多个修补程序适用于较旧的 .NET 运行时版本以添加 TLS 1.2 支持。例如 https://support.microsoft.com/en-us/help/3154518/support-for-tls-system-default-versions-included-in-the--net-framework,CZahrobsky 也可以在Win10 秋季创作者更新,其中还包括修补程序。 (2认同)

小智 5

@沃森

在Windows窗体上,它可以在课程顶部放置

  static void Main(string[] args)
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
       //other stuff here
    }
Run Code Online (Sandbox Code Playgroud)

因为windows是单线程的,所以你需要它,如果它是一个服务你需要把它放在服务的调用之上(因为没有告诉你将在哪个线程).

using System.Security.Principal 
Run Code Online (Sandbox Code Playgroud)

也需要.


Col*_*nic 5

如果您想知道.NET支持哪些协议,可以在https://www.howsmyssl.com/上尝试HttpClient。

// set proxy if you need to
// WebRequest.DefaultWebProxy = new WebProxy("http://localhost:3128");

File.WriteAllText("howsmyssl-httpclient.html", new HttpClient().GetStringAsync("https://www.howsmyssl.com").Result);

// alternative using WebClient for older framework versions
// new WebClient().DownloadFile("https://www.howsmyssl.com/", "howsmyssl-webclient.html");
Run Code Online (Sandbox Code Playgroud)

结果是该死的:

您的客户端使用的TLS 1.0很旧,可能容易受到BEAST攻击,并且没有可用的最佳密码套件。TLS 1.0客户端以及许多更现代的密码套件均无法使用诸如AES-GCM和SHA256之类的替代品来替代MD5-SHA-1。

如Eddie上文所述,您可以手动启用更好的协议:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11; 
Run Code Online (Sandbox Code Playgroud)

我不知道为什么它会立即使用错误的协议。这似乎是一个糟糕的设置选择,相当于一个重大的安全漏洞(我敢打赌,许多应用程序都不会更改默认值)。我们如何举报?