How to migrate a .NET website to TLS 1.2

Posted on Friday, June 29, 2018 at 11:26 PM into code & gotcha by Steve Woods.
Roughly a 2 minute read.

As you might be aware, 30th June 2018 is the deadline for disabling SSL and early versions of TLS in order to meet the PCI Data Security Standard (PCI DSS) for safeguarding payment data, which means you must implement a more secure encryption protocol - TLS 1.1 or higher (TLS v1.2 is recommended).

What is TLS?

Transport Layer Security (TLS) is a cryptographic protocol used to establish a secure communications channel between two computer systems. It is used to authenticate one or both systems with one another, and protects the confidentiality and integrity of any data that passes between them.

Why do I need to update to a newer version?

There are many security vulnerabilities in SSL and early TLS which put companies at risk of being breached. Exploits such as POODLE and BEAST are just a couple of examples of how attackers have compromised systems relying on earlier versions of SSL and TSL.

Unfortunately, there are no fixes or patches that can properly repair SSL or early TLS, so it is critically important that you upgrade to a secure alternative, and disable any fallback to those earlier versions.

How To Update A .NET Application To TLS 1.2

Fortunately, Microsoft have documented the process of migrating applications to newer versions of TLS and the process is fairly straight forward - although it gets progressively more involved the further back in .NET Framework version you go (which, to be honest, you'd expect).

Here's a link to their documentation which helped me a lot: https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls

TL;DR - The Easiest Way

If you're using the latest version of the .NET Framework (or above) which, at the time of writing, is 4.7.2, the easiest method I found was to add the following code to my global.ascx file:

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

If you're using .NET Core, you may wish to enter that into the Configure() method in Startup.cs, however you will need to reference the System.NET namespace - which may or may not be feasible depending on which platform you're targeting. Buyer beware and all that.

Additionally, if you're using external libraries (Dlls) in any type of project, you must make sure that they too have their settings changed.

Sample Code

Place this method in a controller and use it to test your connection to PayPal by enternig its URL into your browser - you should receive a response of 'PayPal_Connection_OK' back from the web service if your server is configured correctly:

public ContentResult TestTLS() {

string paypalUrl = "https://tlstest.paypal.com";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(paypalUrl);
// Set values for the request back
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";

//byte[] param = Request.BinaryRead(Request.ContentLength);
var paramArray = ReadRequestBody(Request.Body);

string strRequest = Encoding.ASCII.GetString(paramArray);

StringBuilder sb = new StringBuilder();
sb.Append(strRequest);

strRequest += sb.ToString();
req.ContentLength = strRequest.Length;

//for proxy
//WebProxy proxy = new WebProxy(new Uri("http://urlort#");
//req.Proxy = proxy;
//Send the request to PayPal and get the response
string response = "";
using (StreamWriter streamOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII))
{
    streamOut.Write(strRequest);
    streamOut.Close();
    using (StreamReader streamIn = new StreamReader(req.GetResponse().GetResponseStream()))
    {
        response = streamIn.ReadToEnd();
    }
}

return Content(response,"text/html");
}

One Important Point Of Note

It's worth noticing that adjusting this setting is an application-wide change because the ServicePointManager is a Singleton - so any subsequent calls that use it will use the security protocol you specify once it has been changed. Of course, this means any calls made before that line is executed will use the SystemDefault value - which may or may not be the older version of TLS that you're trying to get away from. 

For this reason, I recommend trying it in your Global.ascx so that the code is executed immediately on Application_Start();

If entering that line of code doesn't work, be sure to consult the documentation above and take special note of your .NET Framework version. You may need to dig into your Windows registry to disable old versions of TLS + SSL manually, and/or upgrade your .NET Framework version to get things running smoothly.

Happy coding!

;

Comments

Please consider what you post!
Chillax if you're angry.