Which versions of SSL/TLS does System.Net.WebRequest support? - c#

Now that SSL 3 has been found to be vulnerable to the POODLE attack:
Which versions of SSL/TLS does System.Net.WebRequest use when connecting to any https Uri?
I use WebRequest to connect to several 3rd party API's. One of these has now said they will block any request that uses SSL 3. But WebRequest is part of the .Net core framework (using 4.5) so it is not obvious what version it uses.

This is an important question. The SSL 3 protocol (1996) is irreparably broken by the Poodle attack published 2014. The IETF have published "SSLv3 MUST NOT be used". Web browsers are ditching it. Mozilla Firefox and Google Chrome have already done so.
Two excellent tools for checking protocol support in browsers are SSL Lab's client test and https://www.howsmyssl.com/ . The latter does not require Javascript, so you can try it from .NET's HttpClient:
// set proxy if you need to
// WebRequest.DefaultWebProxy = new WebProxy("http://localhost:3128");
File.WriteAllText("howsmyssl-httpclient.html", new HttpClient().GetStringAsync("https://www.howsmyssl.com").Result);
// alternative using WebClient for older framework versions
// new WebClient().DownloadFile("https://www.howsmyssl.com/", "howsmyssl-webclient.html");
The result is damning:
Your client is using TLS 1.0, which is very old, possibly susceptible to the BEAST attack, and doesn't have the best cipher suites available on it. Additions like AES-GCM, and SHA256 to replace MD5-SHA-1 are unavailable to a TLS 1.0 client as well as many more modern cipher suites.
That's concerning. It's comparable to 2006's Internet Explorer 7.
To list exactly which protocols a HTTP client supports, you can try the version-specific test servers below:
var test_servers = new Dictionary<string, string>();
test_servers["SSL 2"] = "https://www.ssllabs.com:10200";
test_servers["SSL 3"] = "https://www.ssllabs.com:10300";
test_servers["TLS 1.0"] = "https://www.ssllabs.com:10301";
test_servers["TLS 1.1"] = "https://www.ssllabs.com:10302";
test_servers["TLS 1.2"] = "https://www.ssllabs.com:10303";
var supported = new Func<string, bool>(url =>
{
try { return new HttpClient().GetAsync(url).Result.IsSuccessStatusCode; }
catch { return false; }
});
var supported_protocols = test_servers.Where(server => supported(server.Value));
Console.WriteLine(string.Join(", ", supported_protocols.Select(x => x.Key)));
I'm using .NET Framework 4.6.2. I found HttpClient supports only SSL 3 and TLS 1.0. That's concerning. This is comparable to 2006's Internet Explorer 7.
Update: It turns HttpClient does support TLS 1.1 and 1.2, but you have to turn them on manually at System.Net.ServicePointManager.SecurityProtocol. See https://stackoverflow.com/a/26392698/284795
I don't know why it uses bad protocols out-the-box. That seems a poor setup choice, tantamount to a major security bug (I bet plenty of applications don't change the default). How can we report it?

When using System.Net.WebRequest your application will negotiate with the server to determine the highest TLS version that both your application and the server support, and use this. You can see more details on how this works here:
http://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake
If the server doesn't support TLS it will fallback to SSL, therefore it could potentially fallback to SSL3. You can see all of the versions that .NET 4.5 supports here:
http://msdn.microsoft.com/en-us/library/system.security.authentication.sslprotocols(v=vs.110).aspx
In order to prevent your application being vulnerable to POODLE, you can disable SSL3 on the machine that your application is running on by following this explanation:
https://serverfault.com/questions/637207/on-iis-how-do-i-patch-the-ssl-3-0-poodle-vulnerability-cve-2014-3566

I also put an answer there, but the article #Colonel Panic's update refers to suggests forcing TLS 1.2. In the future, when TLS 1.2 is compromised or just superceded, having your code stuck to TLS 1.2 will be considered a deficiency. Negotiation to TLS1.2 is enabled in .Net 4.6 by default. If you have the option to upgrade your source to .Net 4.6, I would highly recommend that change over forcing TLS 1.2.
If you do force TLS 1.2, strongly consider leaving some type of breadcrumb that will remove that force if you do upgrade to the 4.6 or higher framework.

Related

How to use tsl version 1.0 in C# server?

Welcome, Im interesting in creating my own local service, witch support TSL v1 only.
I know its weak. But some app does not allow use modern cert above 1.0...
This app has no update to long, and just update it to TSL 1.3/1.2 is impossible.
There two question in complex.
How to create self-signed cert (private and public key) v1.0
How to use this cert in C#, im binding loop back address.
maybe soft like makecert/openssl can help? Which crypt-algorithm i should to use?
This answer is for .NET Core 2.0 and above.
This guide Kestrel web server implementation in ASP.NET Core, it is a guide to create a server.
The certificate and TLS version can be configured in Kestrel server HTTPS defauls:
app.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureHttpsDefaults(listenOptions =>
{
listenOptions.SslProtocols = SslProtocols.Tls;
listenOptions.ServerCertificate = x509Certificate2; // instance of X509Certificate2
});
});
The value SslProtocols.Tls specifies TLS 1.0 security protocol.
How to create a valid, self-signed, X509Certificate2, needed in the code above, is described here. Certificates API was added to .Net Core on 2.0 version.

How to implement TLS 1.2 in ASP.Net Core 2.0

Platform Details: C#, .Net Core 2.0, WS 2016, IIS & Kestrel in reverse proxy
My web app must use HTTPS and TLS 1.2. It was running fine with SSL already, but that is inadequate. I found details online about registry edits needed for TLS 1.2 as default on my web server, and made those changes. After these registry edits, my original code still worked. To force the use of TLS1.2 I added the following to my UseKestrel() in the buildwebhost method.
options =>
{
options.Listen(System.Net.IPAddress.Loopback, 443, listenOptions =>
{
listenOptions.UseHttps(new HttpsConnectionAdapterOptions { SslProtocols = SslProtocols.Tls12 });
}
}))
Now the site is throwing a 502.5. IIS is configured with the original certificate and the site is bound to port 443. I've been told the cert itself is the same between SSL and TLS, so I don't need to get another. When I attempt to debug the code with local host my VS returns an error saying
System.ArgumentException: 'The server certificate parameter is required.'
I have found detail of an "X509Certificate2" object, and some different implementations where the author is using a load method to stream that certificate from a location on the server, but I don't know if that's what's needed here.
The answer is in the comments of the question. The server was provided with an image that didn't include TLS 1.2 by default so the registry edits we did were actually required, but nothing more

TLS Issue using the Demo site

Since today, I am receiving the following error message when sending a package:
Error calling Login: The request was aborted: Could not create SSL/TLS secure channel.
My code
StringBuilder authHeader = new StringBuilder(
$"{{\"Username\":\"{userId}\", \"Password\":\"" +
$"{password}\", \"IntegratorKey\":\"{IntegratorKey}\"");
authHeader.Append(
string.IsNullOrEmpty(senderEmail)
? "}}"
: $",\"SendOnBehalfOf\": \"{senderEmail}\"}}");
Configuration.Default.AddDefaultHeader(
"X-DocuSign-Authentication",
authHeader.ToString());
AuthenticationApi api = new AuthenticationApi();
return api.Login();
Coincidently, today is THE day where TLS1.0 was disables on the demo site of DocuSign. (source)
While I was aware of that, my application uses the .NET 4.7 framework which will uses TLS1.2 by default. Hence, it should not be a problem
As I use the DocuSign NuGet package found here, I looked in the source code and it uses .NET 4.5 (which uses TLS1.0 unless told otherwise)
I understand that I could implement this solution but, shouldn't it work since my application uses .NET 4.7 ?
TLS 1.1 or above is required for all DocuSign APIs and endpoints.
All our libraries now support TLS 1.2 including the the DocuSign eSign C# Nuget package.
See here - https://support.docusign.com/en/articles/End-of-TLS-1-0-and-weak-cipher-support

Multi-threaded SSL / TLS version switching

We have Wcf service (core service) consumed by an asp.net mvc. This core service integrate with other third-party services to achieve some use cases. All these third-party service endpoints are exposed via https but differs when it comes to the supported SSL/TLS versions (1.0,1.1,1.2).
We don’t have much control over this and simply stick a specific ( supported ) SSL/TLS version just before connecting with any given third-party service. i.e. Whenever the core service want to consume any third party service, it set the ServicePointManager.SecurityProtocol to supported SSL/TLS version (third-party ask us to connect using version x.x or higher).
// brief expression of logic which switch TLS version 1.2
var currentSecurityProtocol = ServicePointManager.SecurityProtocol; // get the current security protocol.
try
{
ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
//now get/post data to/from third party service
}
catch (Exception ex)
{
//report it
}
finally
{
ServicePointManager.SecurityProtocol = currentSecurityProtocol;
ServicePointManager.ServerCertificateValidationCallback = null;
}
Question:
How to re-implement the above of TLS version switching logic to work
seamlessly on multi-threaded environment?
I managed to write logic which synchronize access through a lock on ServicePointManager.SecurityProtocol property. But this attempt affect the performance of other connected clients ( when they consume any other third party offering/ service)
You could specify multiple version of Tls so that you don't need to change it during runtime. The below code means that it support TLS1.0, TLS1.1 and TLS1.2.
If the client supports TLS1.2 or below, TLS1.2 is used to create a connection
If the client support TLS1.1 or below, the highest available security protocol which is TLS1.1 is used.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

"The request was aborted: Could not create SSL/TLS secure channel"

Sometimes my client is getting an error during the payment process:
The request was aborted: Could not create SSL/TLS secure channel.
Authorize.NET has been used for the payment system. .Net 4.0 Framework is being used. This error is occurring sometimes, why?
Please try this suggested answer on github to https://github.com/AuthorizeNet/sdk-dotnet/issues/203:
using System.Security.Authentication;
using System.Net
// Prior to your web request ...
const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;
ServicePointManager.SecurityProtocol = Tls12;
(Comment by NexWeb.)
This is happening due to invalid version of .NET Braintree SDK.
You need to update the .NET Braintree SDK you're using to at least version 3.1.0, the minimum version that supports TLS 1.2. Once complete, you can validate your setup using the steps here.
Also, you need to update the .net version from 4.0 to 4.5
For more information, check this link.

Categories