0

My WPF app connects to an Azure Web API. The endpoints will be configured to deny access to any non secured (HTTP) or weakly secured (HTTPS with TLS 1.0 or older) requests. But I also want my App to never even try sending non secured or weakly secured requests.

Microsoft recommends here and there to target the Framework 4.7 and to leave ServicePointManager.SecurityProtocol to its default value so that the OS determines what protocol to use.

The second article I mentioned also indicates Windows 7 will rely on TLS 1.0, just a few lines after having highly recommended not to rely upon TLS 1.0. So I understand I can trust the OS to get the best layer of security it has available, but cannot trust the OS for not sending a request if the best option is still a bad option.

My App relies on System.Net.Http.HttpClient. I would like to make sure that the calls I make through this client are:

  1. Always secured. That is, always use HTTPS, never use HTTP.
  2. Always secured to a sufficient level. That is, rely at least on TLS 1.1; but never TLS 1.0 or SSL.

How can I achieve this?

  • For point 1, I have read I should simply specify "https://" when creating the URI object; is this always true?
  • For point 2, I could do a bitwise combination of all the SecurityProtocolType enum, excluding .ssl3 and .Tls, but that would also exclude any future technologies (TLS1.4?). Is this answer still true now that the .SystemDefault field has been added to the enum?
Community
  • 1
  • 1
Ama
  • 1,373
  • 10
  • 24
  • HttpClient already starts negotiating from the highest version configured in the OS. That's the recommended way of workin, so when TLS1.3 comes out, HttpClient will start using it. What OS are you using? – Panagiotis Kanavos Nov 14 '19 at 13:36
  • Windows 7 default was SSL3 and TLS1.0 until a recent update, where the default has been elevated to TLS1.2 and TLS1.3 support has beed added. Windows 10 defaults to TLS 1.2. When the platform is Windows 7, you probably don't want to rely on the system updates a user may or may not have installed. You can just specify the `SecurityProtocolType` you want to support directly, setting `ServicePointManager.SecurityProtocol`. If you don't, your application simply won't work if the system is not updated. It might be what you want (notify a failure) or not. – Jimi Nov 14 '19 at 13:38
  • Evkaristw Panagiotis. My question is about explicitly excluding some protocols, in case the OS configuration is not picky enough. – Ama Nov 14 '19 at 13:39
  • 1
    See also the notes here: [Which TLS version was negotiated?](https://stackoverflow.com/a/48675492/7444103) – Jimi Nov 14 '19 at 13:39
  • Thanks Jimi. "you probably don't want to rely on the system updates" exactly! But specifying a protocol is also a bad idea, I just want to exclude some. – Ama Nov 14 '19 at 13:41
  • You have to know what you want to support and declare it in the documentation or notify a User that the System doesn't meet the minimum security requirements expected. Or trust your code alone and perform all the required checks. Then, it depends on what you application is for, what the connections you create are for, what services you're connecting to and to what end etc. You can force what you know is the most recent **and** widely supported protocol (which requires some monitoring on your side, so you can provide the required updates) and fail when the remote service doesn't support it. – Jimi Nov 14 '19 at 13:58
  • You can also determine what protocol the remote system is trying to set in the SSL handshake, then notify the user that the connection is not secure when the remote Service requests an ACK on a SSL protocol you don't want to support or you may support if the User decides to allow it. – Jimi Nov 14 '19 at 14:00
  • BTW, you can check what is the higher protocol your .Net framework supports with `public static T GetEnumMaxValue() where T : Enum { var maxValue = Enum.GetValues(typeof(T)).OfType().Max(); return maxValue; }`. The TLS1.3 enumerator value is `var secProtoTLS13 = (SecurityProtocolType)12288;` – Jimi Nov 14 '19 at 14:07
  • I know what minimum level I need, the question is how to exclude anything below it. For example by doing this: `ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol And Not SecurityProtocolType.Ssl3`, but it seems that with the introduction of `.SystemDefault`, this line of code is not valid anymore. – Ama Nov 14 '19 at 14:07
  • 1
    `SystemDefault` returns to the System's default setting. You may use it or not, it's your choice. It may be necessary to ignore it, if the System's default has not been updated to a version that is supported by the framework in use, causing the application to fail most https connections when it could instead work properly. Check the System default: if it's less than what you know the framework and your code can support, force a specific protocol version (TLS1.2 or higher) and also support the consequences of this choice (the validation of the remote servers' certificates, for example.) – Jimi Nov 14 '19 at 14:26
  • Since Windows System from Windows 7 (updated) to Windows 10 support and default to TLS1.2 natively, you may also decide to notify a user that the System is lacking security updates and refuse to run until it is. It depends on the destination of your application. If you want it to run no-matter-what, code it accordingly. This requires more work and a lot deeper knowledge on this matter, though. – Jimi Nov 14 '19 at 14:31
  • You can always add a configuration panel/file to your application and let a user decide whether the application should support a *less secure protocol*, adding support to TLS1.1, or maybe also to earlier protocols, if this is something the users of your application may require. It's their choice now (but you **have** to document it and write a statement on the security risks involved [legal stuff]). – Jimi Nov 14 '19 at 14:44

1 Answers1

1

As Devs said before HttpClient negotiate TLS passing from OS. Especially in W7, isn’t enabled by default to permit applications to use that correctly. In order to resolve that you need to update some keys on registry IF YOU DON’T WANT TO UPDATE .NET FRAMEWORK ON MACHINE WHERE YOUR APP IS RUNNING FOR or you don’t do any update on OS. You can do that by code in VB.Net. In the example below I want to show you THE KEYS which needs to updated/setted. Also if you get this code and create a .reg file and try to execute you resolve the problem in your machine but for distributed apps you need to do that by code in every machine your app is installed. Note that, the label v2.0.50727 or the label v4.0.30319 is the version of .Net framework installed on machine. That means you have to known before the version installed (you can get that also by registry or by code) and if your application is compiled in one of those versions. You can update only the version your app is using for.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2]

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001
G3nt_M3caj
  • 2,497
  • 1
  • 14
  • 16
  • I am not going to take the responsibility of changing the security settings on the machines of my clients. I just want to take the safest protocol amongst those available on the machine. If the safest is below TLS1.1 then I block the process, show a warning message and ask them to get in touch with IT. – Ama Nov 14 '19 at 18:20
  • Even (in this case) you go to change security settings in "better" way, your modus operandi is right. :) – G3nt_M3caj Nov 14 '19 at 19:45