The obscurity of .NET Framework/Java Runtime changes.

“It’s not fair! They promised me they fixed it! It’s not my fault!” – Lando Calrissian.

I was having a conversation recently about the plethora of Java/.NET versions that we end up supporting in the enterprise. Whilst it’s certainly important to place some level of control on the outbreak of versions – and outbreak is the correct word – attempting to standardise versions is extremely difficult due to the subtle changes made in the frameworks/runtimes between versions, and sometimes the dodgyness (also correct word) of some enterprise application developers.

I was recently rewriting my home automation system, going through the journey of decoupling components and creating an enterprise service bus – haven’t we all been there… During this rewrite I made several big changes – the new ESB, and the move to Visual Studio 2015/.NET Framework 4.6. I have an automated testing framework built, and I eventually let it loose on the updated Alarm component. All of a sudden I started having errors connecting with HTTPS to my alarm system. Given I’d been doing quite a bit of coding to get to this point, I had almost forgotten that I was now using .NET 4.6 instead of .NET 4.5 and as a result was quite surprised when the error occurred – given the code that generates the HTTP request to the alarm system hadn’t changed.

Here is an extract of the code and the resulting error message – most of the logic/error handling has been removed to limit the lines of code.

static void Main()
{
	HttpWebRequest wRequest;
	WebResponse wResponse;		

	wRequest = (HttpWebRequest)WebRequest.Create("https://alarmsystem/login.cgi");
	wRequest.Method = "GET";
	wRequest.ServicePoint.Expect100Continue = false;
	wRequest.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;

	wResponse = wRequest.GetResponse();

	wResponse.Close();
}

 I needed to use the ServerCertificateValidationCallback as the alarm system used a self-signed certificate that I hadn’t loaded in the certificate trust store on my development server.

When this code executed, I received the following exception from the GetResponse() call: The request was aborted: Could not create SSL/TLS secure channel.

I did some Wireshark captures and could see that the client was requesting TLS1.2. The server however responded with an SSLv3 response. This caused the client to break the connection and throw the exception. Here are screen captures of the relevant packets.

Client Hello – TLS1.2:

.NET 4.6 Client Hello

Server Hello – SSLv3:

.NET 4.6 Server Hello

You can also see the RST (reset) that followed from the client soon after as it was clearly unhappy with the SSLv3 response from the server. I dropped the client .NET runtime from 4.6 back to 4.5 and tried again. The difference this time was that the client requested TLS1.0, the server responded with SSLv3, and the certificate exchange occurred and the secure session was established.

Client Hello – TLS1.0:

.NET 4.5 Client Hello

Server Hello – SSLv3:

.NET 4.5 Server Hello

Well, staying with the old version of the .NET framework (4.5) would have fixed the problem, but obviously the intent is to keep up with technology and use current versions of the framework. I put the framework back to 4.6, and added an additional line of code to instruct the framework to use SSLv3 for this particular communication. Why was this necessary? The behaviour of the SSL/TLS processing in the 4.6 framework is different to that of 4.5 – despite no change in the code that consumes the function.

static void Main()
{
	HttpWebRequest wRequest;
	WebResponse wResponse;		

	// Enable SSLv3
	ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

	wRequest = (HttpWebRequest)WebRequest.Create("https://alarmsystem/login.cgi");
	wRequest.Method = "GET";
	wRequest.ServicePoint.Expect100Continue = false;
	wRequest.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;

	wResponse = wRequest.GetResponse();

	wResponse.Close();
}

With the code change applied, the secure session was established using SSLv3 and the application could continue.

Client Hello – SSLv3:

4.6 Client Hello (SSLv3)

Server Hello – SSLv3:

4.6 Server Hello

Problem solved. I was able to update the code in my alarm system client to enable the use of the more recent version of the framework.

The key points that I want to make are:

  1. Automated regression testing is critical.
  2. The behaviour of existing functions can and does change between framework/runtime versions.
  3. Trying to keep framework/runtime versions up to date to simplify management and reduce operational/security risk is very difficult when application vendors are slow to adopt new framework/runtime versions.
  4. Developers of IoT type components need a good kick in the a** – this is not the first time I’ve had a network enabled home device either using old protocols or being built with other large security holes.

~ Mike

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s