8

So I am attempting to turn off TLS 1.0 and 1.1 on my server. When I switch off TLS 1.0 I get the following error in my application:

System.ServiceModel.Security.SecurityNegotiationException: The caller was not authenticated by the service. ---> System.ServiceModel.FaultException: The request for security token could not be satisfied because authentication failed.
   at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)
   at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)

When TLS 1.0 is enabled everything works fine.

Now the code calling the service is specifying TLS 1.2 using the ServicePointManager with the following code: ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

The service on the other end is running .Net 4.6.2 and does not specify a TLS protocol using the ServicePointManager, so from what I have read it will automatically detect which TLS protocol is required at runtime in this version of the .net framework.

The Web.config for the WCF services are the following in regards to the bindings

Calling Config:

<basicHttpBinding>
    <binding name="MyBinding" closeTimeout="00:02:00" openTimeout="00:02:00" receiveTimeout="00:02:00" sendTimeout="00:02:00"/>
</basicHttpBinding>
<netTcpBinding>
    <binding name="CrossDomainBinding">
          <security mode="Message">
              <message clientCredentialType="Certificate"/>
          </security>
    </binding>
</netTcpBinding>
<client>
    <endpoint address="net.tcp://MyService.svc"
    binding="netTcpBinding" bindingConfiguration="CrossDomainBinding" behaviorConfiguration="CrossDomainBehavior"
    contract="MyContract" name="MyBinding">
        <identity>
            <certificate encodedValue="CERTIFICATEENCODEDVALUE" />
        </identity>
    </endpoint>
</client>

Service Config:

<bindings>
    <netTcpBinding>
        <binding>
            <security mode="Message">
                <message clientCredentialType="Certificate"/>
            </security>
        </binding>
    </netTcpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="MyBehaviour">
      <serviceMetadata httpGetEnabled="false" httpsGetEnabled="false"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceCredentials>
        <serviceCertificate findValue="MyCertificate" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

I cannot for the life of me work out what the issue is here.

Does anyone have any idea why when turning off TLS 1.0 this does not work?

Jamie Rees
  • 7,973
  • 2
  • 45
  • 83
  • If the code works on Windows, the level of TLS you can have is actually dictated by the underlying OS. You can try SSL hardening, but you need to check your OS Version compatibility first. Also, if you're not sure what version of the protocol is used, try using WireShark to investigate what is negotiated on the wire. – zaitsman Nov 27 '17 at 11:47
  • If you're below Windows 7, that won't work at all. For windows 7: https://support.microsoft.com/en-us/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-a-default-secure-protocols-in For all versions, here's the reference for hardening. BEWARE!! Do not play with these keys over rdp, you may fully lose access to your machine https://technet.microsoft.com/en-us/library/dn786418%28v=ws.11%29.aspx?f=255&MSPPError=-2147217396#BKMK_SchannelTR_TLS10 – zaitsman Nov 27 '17 at 11:48
  • @zaitsman The OS is 2008R2. When I state that I have turned off TLS 1.0, I have turned it off on the OS using the IISCrypto tool. – Jamie Rees Nov 27 '17 at 13:09
  • so both client and server run 2008R2, and on both you've run this tool? (guessing it just sets the registry keys i specified) – zaitsman Nov 27 '17 at 22:34
  • Correct @zaitsman and then manually restart the machines – Jamie Rees Nov 27 '17 at 22:38
  • Well, you do need to check the cipher suite using wireshark. Just disabling TLS 1.0 doesn't explain it, most likely the enabled suites don't match so the client/server can't negotiate an encryption cipher. You will be able to see that clearly in wireshark, and it shouldn't be hard to set that up – zaitsman Nov 27 '17 at 22:40
  • @zaitsman any guide I can follow to see what I'm looking for? I've used wireshark before for a few things, but there is a lot of information. – Jamie Rees Nov 27 '17 at 22:42
  • You can also check the event viewer for SSL errors (there may be a error 40 in the system or application log, although this won't tell you how to fix the problem) – zaitsman Nov 27 '17 at 22:43
  • basically this: https://osqa-ask.wireshark.org/questions/62098/how-to-find-out-which-ssl-cipher-suite-is-being-used Once you have the tcpdump, reading it becomes fairly trivial. – zaitsman Nov 27 '17 at 22:44
  • I shall try in the morning when I'm back at work. – Jamie Rees Nov 27 '17 at 22:45
  • @zaitsman I have been able to see that the client and server are both communicating over TLSv1.2 but I am unable to see which cipher set they are using – Jamie Rees Nov 29 '17 at 09:24
  • if you pastebin the tcpdump somewhere i can take a look... – zaitsman Nov 29 '17 at 09:31
  • The caller does not decide what version of TLS to use. Even in 4.6+ the service is required to specify SecurityProtocolType.Tls12. The caller will negotiate with the host server. – Dwayne Hinterlang Dec 02 '17 at 21:17
  • @Dwayne Hinterlang I have also set that on the host server and still same issue – Jamie Rees Dec 02 '17 at 22:21

1 Answers1

3

As you know, the problem is SSL3 and TLS1.0 are vulnerable to POODLE attack, and other threads. So, migrating to .NET 4.5, which supports TLS 1.1 and TLS 1.2, or above is a good idea.

Basically, the client will negotiate with the server and take the highest protocol that server provides. As long as server provides TLS 1.1 or TLS 1.2, the client will use theTLS 1.1 or 1.2.

If your app is .NET 4.0, you can still use TLS 1.2 by installing .NET 4.5 on your server. Your app will not have to be retargeted to .NET 4.5. You can forcefully change the protocol in .NET 4.0 app as shown below (and already do):

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;//SecurityProtocolType.Tls1.2;

One caveat is simply upgrading to .NET 4.5 does not automatically solve the problem. That is because the default protocol is SSL3/TLS1.0 in .NET 4.0/4.5. So in order to use TLS 1.2 or TLS 1.1 in .NET 4.5+, you will need to set SecurityProtocol (using the SslProtocols Enumeration or the corresponding integer values) before any WebRequest calls (actually, this has to be done only once per AppDomain. But it does not hurt to set it again).

In the first place, TLS is terminated in Windows by a component called SChannel. The supported ciphers are dependent on the version of SChannel, which is dependent on the OS, NOT on the .NET version; e.g. Windows XP only supports up to TLS 1.0. Ref.
Since Windows Server 2012 and Windows 8.1 TLS 1.2 is enabled by default. So, you should be fine.

However, it is worth to check if TLS 1.2 is enabled at OS level and in the registry (this also affects IIS (7.x), SQL Server (2012), Reporting Services, etc. depending on the build version). The default security protocol depends on the following registry entry.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319: SchUseStrongCrypto to DWORD 1

Check if the registry key "SchUseStrongCrypto" is set to 1. This will force .NET apps to avoid using SSL3.0 or TLS1.0 and always use the strongest protocol available.

I hope this helps!

wp78de
  • 18,207
  • 7
  • 43
  • 71