0

For testing purposes, I am trying to force my code to use an outdated version of TLS to trigger a particular API response.

However, despite TLS 1.0 shown as being used, the request succeeds. The endpoint used only allows for TLS 1.2.

using System.Net;


namespace MyNameSpace {
    class myApp {
        private static readonly HttpClient client = new HttpClient();

        static void Main(string[] args) {
            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
            ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls; // This is TLS 1.0

            Console.WriteLine(ServicePointManager.SecurityProtocol);
            MakeRequest();
            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }

        public async static void MakeRequest() {
            var responseString = await client.GetStringAsync("https://api.twilio.com:8443");
            Console.WriteLine(responseString);

        }   
    }
}

This code returns

>>> dotnet run
Tls
Press any key to exit...
<?xml version='1.0' encoding='UTF-8'?>
<TwilioResponse><Versions><Versions><Version><Name>2010-04-01</Name><Uri>/2010-04-01</Uri><SubresourceUris><Accounts>/2010-04-01/Accounts</Accounts></SubresourceUris></Version></Versions></Versions></TwilioResponse>

However, when forcing cURL to use TLS 1.0 the request fails as it should:

> curl -v https://api.twilio.com:8443 --tlsv1.0 --tls-max 1.1

*   Trying 52.2.204.41...
* TCP_NODELAY set
* Connected to api.twilio.com (52.2.204.41) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.1 (OUT), TLS handshake, Client hello (1):
* TLSv1.1 (IN), TLS alert, protocol version (582):
* error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert protocol version
* Closing connection 0
curl: (35) error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert protocol version

How can I force my code to use an OUTDATED version of TLS to trigger this error? Right now, my setting doesn't seem to stick.

NB: From what I can gather I am using .NET 6.0.1

Addendum: It was suggested to set the protocol before instantiating the HTTPClient. An even simpler example yields the same result, code below:

using System.Net;

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

HttpClient client = new HttpClient();

Console.WriteLine(ServicePointManager.SecurityProtocol);

var responseString = await client.GetStringAsync("https://api.twilio.com:8443");
Console.WriteLine(responseString);
mmenschig
  • 1,088
  • 14
  • 22
  • Interesting. when I search for forcing an insecure protocol, not much in the way of hits. – Mitch Wheat Dec 18 '21 at 00:16
  • just a guess - but perhaps `client` needs to be instantiated after the protocol is set. – Andrew S Dec 18 '21 at 00:20
  • 1
    @MitchWheat that's exactly my conundrum unfortunately. For reasons unknown, nobody appears to want to use an insecure protocol anymore ;) – mmenschig Dec 18 '21 at 00:20
  • @AndrewS Just tried that and updated my post, same result. – mmenschig Dec 18 '21 at 00:28
  • what version of .NET are you using? I'm thinking that later versions might force highest protocol? – Mitch Wheat Dec 18 '21 at 00:43
  • @MitchWheat I am using version 6.0.101 - specified in the root level `global.json` – mmenschig Dec 18 '21 at 00:50
  • Are you certain that you even have TLS 1.0 cyphers on your source machine? – David L Dec 18 '21 at 01:10
  • @DavidL most certainly I am not. But if cURL can use 1.0...? Is that an incorrect assumption? How would I verify – mmenschig Dec 18 '21 at 01:17
  • If cURL can negotiate over TLS 1.0, that would indicate that the cyphers are present. I can't find any explicit documentation, but I sincerely doubt that .NET 6 will allow TLS 1.0 to be used. Most likely it can't even negotiate it. – David L Dec 18 '21 at 01:19
  • 1
    In .Net 6: `var client = new HttpClient(new HttpClientHandler() { SslProtocols = System.Security.Authentication.SslProtocols.Tls });` -- There's no need, in your code, to repeat `ServicePointManager.SecurityProtocol` twice. -- BTW, download IIS Crypto from [here](https://www.nartac.com/Products/IISCrypto) (free software) and check what's available / enabled in your System. – Jimi Dec 18 '21 at 01:45
  • Or, use HttpWebRequest and see the notes here: [Which TLS version was negotiated?](https://stackoverflow.com/a/48675492/7444103) – Jimi Dec 18 '21 at 01:50
  • 1
    @Jimi That did the trick! You should post it as an answer so I can accept it. Thank you – mmenschig Dec 18 '21 at 01:56
  • @Jimi One question remains however, why does using ServicePointManager have seemingly no effect? – mmenschig Dec 18 '21 at 02:01
  • The HttpClient initialization you're using sets a default HttpClientHandler with, well, default options, including `SslOptions.EnabledSslProtocols`, which defaults to `SslProtocols.Default` (hence TLS 1.2) -- Sorry, I cannot post answers (don't ask). Post the answer yourself, I'll delete the comments. – Jimi Dec 18 '21 at 02:11

0 Answers0