System.Net.WebRequest 支持哪些版本的 SSL/TLS?

82

现在SSL 3已经被发现容易受到POODLE攻击的影响:

System.Net.WebRequest连接到任何https Uri时使用哪些版本的SSL/TLS?

我使用WebRequest连接到多个第三方API。其中之一已经表示将阻止使用SSL 3的任何请求。但是,因为WebRequest是.NET核心框架(使用4.5)的一部分,所以不明显它使用的是哪个版本。


WebRequest会在服务器(或中间人)请求时回退到SSL 3吗? - Philip Pittle
如果我没记错的话,我认为 WebRequest 查看您尝试访问的服务器上的安全证书,并使用 Web 服务器上的任何加密模式。我认为您不需要在客户端进行任何更改。 - Icemanind
1
我希望刚刚表示不支持SSL3的API所有者已经考虑到确保他们的服务器不会请求客户端使用SSL3 :) - JK.
@iceman 有没有办法从证书中判断它是否支持SSL3?我没有看到与版本相关的任何属性。 - JK.
@JK. - 我不确定其他浏览器,但我正在使用Chrome。在Chrome中,如果您访问一个HTTPS网站(例如Wellsfargo.com),您会在URL附近看到一个绿色锁。单击该锁,然后单击连接选项卡,它将向您显示。针对wellsfargo.com的情况,Chrome会显示“连接使用TLS 1.0”。IE和其他浏览器应该显示类似的内容。 - Icemanind
@icemanind。这将展示给您您的浏览器如何连接到服务器:这将是服务器支持的选项子集。有关服务器支持的完整详细信息 | 有关您的浏览器支持的完整详细信息 - TRiG
3个回答

53

这是一个重要的问题。SSL 3协议(1996)已被2014年发布的Poodle攻击彻底破坏。IETF已经发布了"SSLv3 MUST NOT be used"。Web浏览器正在摒弃它。 Mozilla FirefoxGoogle Chrome已经这样做了。

检查浏览器协议支持的两个出色工具是SSL实验室的客户端测试https://www.howsmyssl.com/。后者不需要Javascript,所以您可以从.NET的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客户端不可用,还有许多更现代的密码套件。

这很令人担忧。它相当于2006年的Internet Explorer 7。

要列出HTTP客户端支持的确切协议,您可以尝试下面针对每个版本的测试服务器:

var test_servers = new Dictionary<string, string>();
test_servers["SSL 2"] = "https://www.ssllabs.com:10200";
test_servers["SSL 3"] = "https://www.ssllabs.com:10300";
test_servers["TLS 1.0"] = "https://www.ssllabs.com:10301";
test_servers["TLS 1.1"] = "https://www.ssllabs.com:10302";
test_servers["TLS 1.2"] = "https://www.ssllabs.com:10303";

var supported = new Func<string, bool>(url =>
{
    try { return new HttpClient().GetAsync(url).Result.IsSuccessStatusCode; }
    catch { return false; }
});

var supported_protocols = test_servers.Where(server => supported(server.Value));
Console.WriteLine(string.Join(", ", supported_protocols.Select(x => x.Key)));

我正在使用 .NET Framework 4.6.2。我发现HttpClient仅支持SSL 3和TLS 1.0。这是类似于2006年的Internet Explorer 7。


更新: 原来HttpClient确实支持TLS 1.1和1.2,但您需要手动打开它们在System.Net.ServicePointManager.SecurityProtocol。请参见https://dev59.com/zV8d5IYBdhLWcg3w1FB0#26392698

我不知道为什么它默认使用不安全的协议。这似乎是一个糟糕的设置选择,相当于一个重大的安全漏洞(我敢打赌很多应用程序没有更改默认值)。我们该如何报告这个问题?


我必须使用哪种协议? - Kiquenet
有没有测试TLS1.3的服务器? - sgmoore

53
使用 System.Net.WebRequest 时,您的应用程序会与服务器协商确定双方都支持的最高 TLS 版本并使用它。您可以在此处查看有关其工作原理的更多详细信息:http://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake
如果服务器不支持 TLS,则会回退到 SSL,因此可能会回退到 SSL3。您可以在此处查看 .NET 4.5 支持的所有版本:http://msdn.microsoft.com/en-us/library/system.security.authentication.sslprotocols(v=vs.110).aspx
为了防止您的应用程序易受 POODLE 攻击,请按照这个说明在运行您的应用程序的计算机上禁用 SSL3:https://serverfault.com/questions/637207/on-iis-how-do-i-patch-the-ssl-3-0-poodle-vulnerability-cve-2014-3566

20
我建议,为了使像 WebRequest 和 HttpWebRequest 这样的 outbound 请求更加安全,您应该按照我在 https://dev59.com/zV8d5IYBdhLWcg3w1FB0 上提出的问题中详细说明的步骤来禁用 SSL 回退。基本上,您首先运行以下代码:System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; 据我所知,这个答案中详细说明的注册表修复只适用于入站连接。 - Jordan Rieger
1
请注意,在 .NET Framework 3.5 或更低版本中,您只有使用 SecurityProtocolType.Tls(因此仅支持 TLS 1.0)的选项。 - James Westgate
如果我放弃System.Net.WebRequest并使用另一个库(如RestSharp),是否可以获得更高的TLS支持?还是需要升级实际的.NET框架? - The Muffin Man
我相信这是需要升级的实际 .net 框架。www.passionatecoder.ca - Ehsan
1
@JamesWestgate 我的理解是 TLS 实际上是在操作系统/机器级别实现的东西?HTTP 流量不是在那里发生的吗?因此,我认为告诉您的代码使用特定的 TLS 并没有意义,因为这实际上是由操作系统决定的。 - Don Cheadle
@mmcrae - 我只是在特别回应Jordan Rieger上面的评论,因为那段代码在 .net 4.0以下的版本中是无法工作的。我也不想硬编码协议选项。 - James Westgate

8
我在那里也提供了一个答案,但@Colonel Panic的更新文章建议强制使用TLS 1.2。将来,当TLS 1.2被破解或被取代时,将你的代码固定在TLS 1.2上将被视为一种缺陷。在.NET 4.6中默认启用与TLS1.2的协商。如果您有升级到.NET 4.6的选项,我强烈建议您进行更改而不是强制使用TLS 1.2。
如果您确实强制使用TLS 1.2,请考虑留下某种类型的面包屑,以便在升级到4.6或更高版本框架时取消该强制性要求。

2
默认情况下,.Net 4.6启用了与TLS1.2的协商。您有相关文档吗? - felickz
2
当时,我们发现了一些不确定的文档,暗示了这个功能(请参见 https://msdn.microsoft.com/en-us/library/system.net.security.sslstream(v=vs.110).aspx ,就在示例上面)。然而,我们通过创建一个测试程序并使用一个被锁定到TLS 1.2的服务器以及使用Web请求尝试下载页面来验证了这一点。然后我们改变了程序的框架版本。所有低版本都无法连接,但是.NET 4.6没有任何问题地连接上了。 - Prof Von Lemongargle
感谢提供详细信息,我看到很多API提供商指出4.5不能连接到TLS 1.2,但我很难提供任何官方文档,只能依靠社区的支持 :) - felickz
这是正确的做法。我们有许多旧服务器与现在坚持使用TLS的Web端点进行通信。Web服务引用开始因SSL/TLS错误而失败。您可以黑客式地修改注册表,但升级服务器到最新的.NET版本更容易、更安全。 - Neil Laslett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接