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

我正试图减轻我们对Poodle SSL 3.0 Fallback攻击的脆弱性。 我们的pipe理员已经开始禁用SSL,而使用TLS来连接我们的服务器。 而且我们还build议我们的团队在他们的网页浏览器中禁用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 Ssl3 | Tls (虽然我找不到文档来支持它)。SecurityProtocolType是一个带有Flags属性的枚举,所以它是这两个值的一个按位 。 您可以使用以下这行代码在您的环境中检查:

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

  3. 在应用程序中启动任何连接之前,应将其更改为TlsTls12

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

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

TLS 1.0和1.1 / 1.2更新:

根据谷歌安全专家亚当·兰利(Adam Langley)的说法, 后来发现TLS 1.0如果执行不当 , 很容易受到POODLE的影响 ,所以你应该考虑专门转向TLS 1.2。

我们正在做同样的事情。 要仅支持TLS 1.2并且不支持SSL协议,您可以这样做:

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

SecurityProtocolType.Tls只是TLS 1.0,不是所有的TLS版本。

作为一个方面:如果你想检查你的网站不允许SSL连接,你可以在这里做(我不认为这会受上述设置的影响,我们不得不编辑registry来强制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

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

研究表明,协商阶段需要ALPN协商协议才能到达TLS1.2。 我们以此为起点,尝试使用.Net框架的更新版本来查看支持开始的位置。 我们发现.Net 4.5.2不支持与TLS 1.2协商,但.Net 4.6却支持。

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

更新:从评论工作,我build立这样的:

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

为了validation这个概念,我还是把SSL3和TLS1.2放在一起,然后运行代码来定位一个只支持TLS 1.0和TLS 1.2(1.1被禁用)的服务器。 使用or'd协议,似乎连接正常。 如果我更改为SSL3和TLS 1.1,则无法连接。 我的validation使用从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(); 

而这工作:

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

与强制TLS 1.2相比,这样做有一个优点,如果.Net框架已经升级,Enum中有更多的条目,它们将被代码原样支持。 它比使用.Net 4.6有一个缺点,那就是4.6使用ALPN,如果没有指定限制,应该支持新的协议。

@沃森

在窗体上它是可用的,在类的顶部放

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

因为windows是单线程的,所有你需要的,如果你的服务需要把它放在服务调用的上面(因为没有告诉你将使用什么线程)。

 using System.Security.Principal 

也是需要的。

如果你对.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"); 

结果是诅咒:

您的客户端正在使用TLS 1.0,这是非常古老的,可能受到BEAST攻击,并没有最好的密码套件。 另外像AES-GCM和SHA256取代MD5-SHA-1对于TLS 1.0客户端以及更多的现代密码套件是不可用的。

正如Eddie上面解释的那样,您可以手动启用更好的协议:

 System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11; 

我不知道为什么它使用错误的协议开箱即用。 这似乎是一个糟糕的设置select,无异于一个重大的安全漏洞(我敢打赌,大量的应用程序不会改变默认)。 我们如何报告?

我不得不投入相当于整数,我仍然使用.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, } */