8
votes

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?

1
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
If you're below Windows 7, that won't work at all. For windows 7: support.microsoft.com/en-us/help/3140245/… 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 technet.microsoft.com/en-us/library/…zaitsman
@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
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
Correct @zaitsman and then manually restart the machinesJamie Rees

1 Answers

3
votes

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!