.NET 4.8: What evaluates Net.ServicePointManager.SecurityProtocol=SystemDefault to? TLS 1.2 problems
Asked Answered
I

2

8

I have a .NET 4.8 application which is a small Excel Add-in (thus running in Office/Excel) which performs HTTP (REST) requests and shows the data in Excel.

On the webserver we reconfigured to only allow TLS 1.2 and suddenly the HTTP Requests do not work anymore with this WebException: The underlying connection was closed: An unexpected error occurred on a send.

Test-client OSes are Windows 10 and 8 (fully patched). Thus supporting TLS 1.2 according to https://learn.microsoft.com/en-us/dotnet/framework/network-programming/tls : "Supported, and enabled by default."

Executing the following in PowerShell gives:

[Net.ServicePointManager]::SecurityProtocol
SystemDefault

The following registry keys - which are often mentioned in documentation and blogs - are NOT set (they do not exist - also not the WOW6432Node variants):

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319\SystemDefaultTlsVersions
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319\SchUseStrongCrypto
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp\DefaultSecureProtocols

Setting HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319\SchUseStrongCrypto=1 "fixes" the problem.

I can also manually enable TLS 1.2 and the problem goes away, but that removes control from the OS back to the application, which does not seem to be the underlying idea of .NET 4.8: ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;

My questions:

  • How can I find out what SystemDefault evaluates to in .NET. How can I find this?
  • Why does TLS 1.2 not seem to enabled without setting registry keys?
  • My assumption is that TLS 1.2 should be supported with .NET 4.8 without any system modifications (like registry keys) and without any code changes. Is this assumption wrong?

Addition I found these Github .net issues which seem to describe what I experience:

GitHub: Not getting default values on .NET 4.7.2 on Windows 10 (1709)

GitHub: The Windows 10 .Net 4.8 Oct update removes TLS 1.1, 1.2. 1.3 from default security protocols from .Net apps forcing traffic to use SSL3 and TLS 1.0.

Unfortunately I have no machines old enough to not have the KB update yet. I may not be asking at the right place here, but is it possible that .NET 4.8 requires registry keys to get proper TLS 1.2 working?

Indubitability answered 2/2, 2021 at 15:33 Comment(14)
Are you sure the error isn't due to incomplete TLS1.3 support??Represent
Yes I am sure. We only enabled TLS 1.2 serverside.Indubitability
UPDATE: I still don't have a solution and am really stumped why TLS 1.2 is not enabled. I checked multiple Windows 10 machine, none have the SchUseStrongCrypto key. Any ideas?Indubitability
Just throwing this out there. I have battled with this myself and just add in the TLS 1.2 value. Once the value is in place, it takes affect immediately. Take a look at this: pastebin.com/0v5quVJL It only affects the current user, not the entire machine.Precess
ServicePointManager.SecurityProtocol = SystemDefault is the default when you are (actually) targeting .Net 4.8, so setting / adding SystemDefaultTlsVersions is irrelevant. If your app gets the expected results adding and setting SchUseStrongCrypto, then you're not actually targeting .Net 4.8 (or you think your app is, but a dependency may not), since this Key is not relevant in .Net 4.8. You can use app.config to opt-out, otherwise you opt-in by default. Since you're on Windows 10, the default is TLS1.2. TLS13 is not functional (except in Windows Server 2021).Cosimo
Setting ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 (not |=) is only required in Windows 7 / Windows Server 2008 R2 or to enable the Protocol in a debugging section if you use Visual Studio versions prior to 2017 (it's a debugger issue).Cosimo
I am using Visual Studio 2019 and I read about the debugger issue, yes. But even when I make a release build of a simple console app I get the problem I reported. Since I cannot get an authoritative answer on this issue and cannot rely on clients setting registry keys I probably will be adding ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 to my release code. BTW my idea was with the |= that TLS1.2 gets added to whatever .NET sets.Indubitability
You don't want to add TLS12 to SSL3. Anyway, you can make a pre-test (before you start exchanging data) and refuse the connection, in case you don't agree with the Protocol that comes out of the handshake. See: Which TLS version was negotiated?Cosimo
Note that in that code, all Protocols are enabled for testing, you should enable only what you want to support. You can also add the option, for the Users, to enable other protocols, if needed. -- Anyway, read my first comment: if you could make it work setting SchUseStrongCrypto = 1 in the Registry, then you're not using .Net 4.8: that .Net version has automatic opt-in for this (the Registry key is useless). You can only opt-out. Check your build and the dependencies / libraries / whatever that query HTTPS resources.Cosimo
@Cosimo I have <TargetFrameworkVersion>v4.8</TargetFrameworkVersion> in my project.csproj so that does target 4.8 AFAIK. Can there be anything else that would force a lower version of .NET 4.8 to be targeted or used?Indubitability
I have included a handful of libraries. Is there a way to check libraries for which .NET version they use? Or can I overwrite that?Indubitability
I checked with ILSpy: my own DLL does target .NET 4.8. However, I have libraries which target 2.0 and 4.5 in use. Can that explain my problems?Indubitability
Yes, that can explain it. Also check app.config, see whether you have other sku options there. Anyway, I think you're on the right track now.Cosimo
It has to do with an older framework version being used. For 4.8 the registry value will default to 1 (enabled) learn.microsoft.com/en-us/dotnet/framework/network-programming/…Chrisse
C
1

The default setting in .NET versions is related to the operating systems it can run on. Several older versions of Windows do not support TLS 1.2 So the default for .NET is use what ever setting the Operating System is using. While both Windows 10 and 8 support TLS 1.2 it is not enabled by default.

The link below is Microsoft's documentation on how to enable TLS 1.2 on most versions of Windows. It specifically mentions setting the following two registry settings:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp\
      DefaultSecureProtocols = (DWORD): 0xAA0
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp\
      DefaultSecureProtocols = (DWORD): 0xAA0

https://learn.microsoft.com/en-us/mem/configmgr/core/plan-design/security/enable-tls-1-2-client

Update

A couple of other areas that could cause this problem:

  1. Just because you are compiling against .NET 4.8 doesn't mean your app is configured to run on 4.8. It will default to what ever version of .NET it was originally compiled to run on. So if it was version 4.6 or older that may be the issue.

  2. Older versions of Office will only work against certain versions of .NET https://learn.microsoft.com/en-us/visualstudio/vsto/running-solutions-in-different-versions-of-microsoft-office?view=vs-2019

In the following document on TLS best practices it states

Do not specify the TLS version. Configure your code to let the OS decide on the TLS version.

https://learn.microsoft.com/en-us/dotnet/framework/network-programming/tls

Chieftain answered 10/3, 2021 at 23:25 Comment(1)
The registry key that you mentioned does nothing for me, but like I wrote in my post, the SchUseStrongCrypto=1 setting does work for my .net application. However, what I just cannot wrap my head around is that a modern OS (Win10) requires a system modification to support TLS 1.2 for clients. That just cannot be, right? Security must never be opt-in, this is a serious design flaw in my opinion...Indubitability
P
-1

I have recently been through the same painful process of getting TLS 1.2 to work. In general there are three thing to look out for.

  • You should let .NET use the system default and not try to override it in code like setting ServicePointManager.SecurityProtocol.
  • Second thing to watch out for is that both the .net version and the OS must support TLS 1.2
  • Lastly the cipher suite used to secure the TLS 1.2 tunnel must be supported by both sides.

What helped me a lot was this overview and guidelines from MS TLS best practices

So to answer your questions:

  1. It depends on the OS, use the link to find out the specifics
  2. Again it depends on the .net version and the os
  3. And again it depends on the os
Primp answered 2/2, 2021 at 15:50 Comment(3)
I don't set ServicePointManager.SecurityProtocol except for this quick test. .NET 4.8 and WIndows 10 support TLS 1.2. I have not checked the ciphersuites, are there ciphers which .NET 4.8 does not support?Indubitability
Windows 10 and windows server 2016 in combination with .net 4.8 should work 'out-of-the-box'. If you want to know which cipher suites are used you should look at using openssl to get more details. Alternatively you can inspect the certificate using a browser, but I'm not sure if that is possible in your scenario.Primp
Yes, exactly it should work out of the box. That's why I asked my 3 questions. I checked, the ciphers are supported on both sides. Something is really strange, and I am not understanding what.Indubitability

© 2022 - 2024 — McMap. All rights reserved.