Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable SSL fallback and use only TLS for outbound connections in .NET? (Poodle mitigation)

Tags:

.net

ssl

I am trying to mitigate our vulnerability to the Poodle SSL 3.0 Fallback attack. Our admins have already started disabling SSL in favor of TLS for inbound connections to our servers. And we have also advised our team to disable SSL in their web browsers. I'm now looking at our .NET codebase, which initiates HTTPS connections with various services through System.Net.HttpWebRequest. I believe that these connections could be vulnerable to a MITM attack if they allow fallback from TLS to SSL. Here is what I have determined so far. Could some one please double-check this to verify that I am right? This vulnerability is brand new, so I have yet to see any guidance from Microsoft on how to mitigate it in .NET:

  1. The allowed protocols for the System.Net.Security.SslStream class, which underpins secure communication in .NET, are set globally for each AppDomain via the System.Net.ServicePointManager.SecurityProtocol property.

  2. The default value of this property in .NET 4.5 is Ssl3 | Tls (although I can't find documentation to back that up.) SecurityProtocolType is an enum with the Flags attribute, so it's a bitwise OR of those two values. You can check this in your environment with this line of code:

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

  3. This should be changed to just Tls, or perhaps Tls12, before you initiate any connections in your app:

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

  4. Important: Since the property supports multiple bitwise flags, I assume that the SslStream will not automatically fallback to other unspecified protocols during handshake. Otherwise, what would be the point of supporting multiple flags?

Update on TLS 1.0 vs 1.1/1.2:

According to Google security expert Adam Langley, TLS 1.0 was later found to be vulnerable to POODLE if not implemented correctly, so you should consider moving to TLS 1.2 exclusively.

Update for .NET Framework 4.7 and above:

As alluded to by Prof Von Lemongargle below, starting with version 4.7 of the .NET Framework, there is no need to use this hack as the default setting will allow the OS to choose the most secure TLS protocol version. See Transport Layer Security (TLS) best practices with the .NET Framework for more information.

like image 247
Jordan Rieger Avatar asked Oct 15 '14 18:10

Jordan Rieger


People also ask

Which SSL protocol should I disable in domain controllers?

Before disabling SSL 2.0, SSL 3.0 and TLS 1.0 protocols in Domain Controllers, we had better ensure all machines and apps in your AD domain do not use SSL 2.0, SSL 3.0 and TLS 1.0 protocols and all machines and apps use TLS 1.1 or TLS 1.2.

Which TLS version is most vulnerable to POODLE attacks?

According to Google security expert Adam Langley, TLS 1.0 was later found to be vulnerable to POODLE if not implemented correctly, so you should consider moving to TLS 1.2 exclusively. Update for .NET Framework 4.7 and above:

What version of TLS should I enable/disable?

So we can enable TLS 1.1 or TLS 1.2 and disable SSL 2.0, SSL 3.0 and TLS 1.0 protocols via GPO registry on all machines, in this way, Windows machines and Microsoft Apps should/will use TLS 1.1 or TLS 1.2.

What if TLS_FALLBACK_SCSV doesn’t support TLS?

In the past, browsers that didn’t yet support TLS_FALLBACK_SCSV would try to reconnect by using an older protocol version, such as SSL 3.0, to avoid a second crash. I.e., instead of reaching a consensus about the highest possible version, they would downgrade to one that is certain to work.


3 Answers

We are doing the same thing. To support only TLS 1.2 and no SSL protocols, you can do this:

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

SecurityProtocolType.Tls is only TLS 1.0, not all TLS versions.

As a side: If you want to check that your site does not allow SSL connections, you can do so here (I don't think this will be affected by the above setting, we had to edit the registry to force IIS to use TLS for incoming connections): https://www.ssllabs.com/ssltest/index.html

To disable SSL 2.0 and 3.0 in IIS, see this page: https://www.sslshopper.com/article-how-to-disable-ssl-2.0-in-iis-7.html

like image 200
Eddie Fletcher Avatar answered Oct 12 '22 04:10

Eddie Fletcher


@Eddie Loeffen's answer seems to be the most popular answer to this question, but it has some bad long term effects. If you review the documentation page for System.Net.ServicePointManager.SecurityProtocol here the remarks section implies that the negotiation phase should just address this (and forcing the protocol is bad practice because in the future, TLS 1.2 will be compromised as well). However, we wouldn't be looking for this answer if it did.

Researching, it appears that the ALPN negotiation protocol is required to get to TLS1.2 in the negotiation phase. We took that as our starting point and tried newer versions of the .Net framework to see where support starts. We found that .Net 4.5.2 does not support negotiation to TLS 1.2, but .Net 4.6 does.

So, even though forcing TLS1.2 will get the job done now, I recommend that you upgrade to .Net 4.6 instead. Since this is a PCI DSS issue for June 2016, the window is short, but the new framework is a better answer.

UPDATE: Working from the comments, I built this:

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

In order to validate the concept, I or'd together SSL3 and TLS1.2 and ran the code targeting a server that supports only TLS 1.0 and TLS 1.2 (1.1 is disabled). With the or'd protocols, it seems to connect fine. If I change to SSL3 and TLS 1.1, that failed to connect. My validation uses HttpWebRequest from System.Net and just calls GetResponse(). For instance, I tried this and failed:

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

while this worked:

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

This has an advantage over forcing TLS 1.2 in that, if the .Net framework is upgraded so that there are more entries in the Enum, they will be supported by the code as is. It has a disadvantage over just using .Net 4.6 in that 4.6 uses ALPN and should support new protocols if no restriction is specified.

Edit 4/29/2019 - Microsoft published this article last October. It has a pretty good synopsis of their recommendation of how this should be done in the various versions of .net framework.

like image 25
Prof Von Lemongargle Avatar answered Oct 12 '22 05:10

Prof Von Lemongargle


I had to cast the integer equivalent to get around the fact that I'm still using .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,
   } 
*/
like image 7
CZahrobsky Avatar answered Oct 12 '22 03:10

CZahrobsky