Search code examples
c#sslhttps.net-4.6.2.net-4.7

.net 4.7 fails to create SSL channel when server responds with TLS 1.1


I'm trying to do HTTPS GET request using client certificate authentication and it fails with

The request was aborted: Could not create SSL/TLS secure channel.

I'm trying same request using Java and it works fine, I see following in Java logs (stripped to only interesting parts):

*** ClientHello, TLSv1.2
main, WRITE: TLSv1.2 Handshake, length = 185

....

*** ServerHello, TLSv1.1
main, READ: TLSv1.1 Handshake, length = 3339

Which as I understand means, that server for some reason does not support TLS 1.2, but client is accepting that and simply fall backs to TLS 1.1.

When I set

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11;

.NET works fine too. Now the question - why .NET does not fall back to TLS 1.1 as Java did, can I enable that fallback somehow (without actually trying TLS 1.2, catch exception and try with TLS 1.1)?


Solution

  • In description of ServicePointManager.SecurityProtocol it is stated

    Note that no default value is listed for this property, on purpose. The security landscape changes constantly, and default protocols and protection levels are changed over time in order to avoid known weaknesses. Defaults will vary depending on individual machine configuration, and on which software is installed, and on which patches have been applied.

    Your code should never implicitly depend on using a particular protection level, or on the assumption that a given security level is used by default. If your app depends on the use of a particular security level, you must explicitly specify that level and then check to be sure that it is actually in use on the established connection. Further, your code should be designed to be robust in the face of changes to which protocols are supported, as such changes are often made with little advance notice in order to mitigate emerging threats.

    While on .NET 4.7 the default value of this property should be SystemDefault (source) and SystemDefault means "ask OS about list of default protocols" (and on Windows 10 TLS 1.1 and TLS 1.2 are enabled) - this value still can be affected by multiple external sources (such as registry keys and as you see above even by installed software or applied patches). As we figuted out in comments, for some reason you have it as Ssl3 | Tls by default, which is bad, because Ssl3 is not even secure and should be disabled.

    So to solve your issue (and in future such cases) - always list protocols you need, especially if you publish your applicaiton on multiple client machines, because default setting is not reliable:

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