Danger: Bypass SSL Interception Proxy Server Certificate Validation in .NET or Python HTTP Requests

Raymond Raymond event 2024-01-05 visibility 300
more_vert
Danger: Bypass SSL Interception Proxy Server Certificate Validation in .NET or Python HTTP Requests

In enterprise environment, it is common to setup SSL interception via a proxy server. SSL interception is a technique used by a proxy server to decrypt and inspect the encrypted traffic between a client (like a web browser) and a server (like a website), before re-encrypting it and sending it on its way. This is often referred to as a “man-in-the-middle” attack.

The problem

In most setup, the proxy server will return an internal certificate to the client that is usually trusted already by the client user/machine. In some cases, the client machines might not be setup correctly, i.e. not added into trust store of the machines. This causes SSL connection fails in many applications or code.

For example, in Python, it may generate the following error (routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed):

import requests

url = 'https://example.com'
response = requests.get(url)

# This will raise an error if the SSL certificate is not trusted:
# requests.exceptions.SSLError: [Errno 1] _ssl.c:503: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

In .NET, the following code can raise similar exception if the intercepted public cert from proxy server is not trusted.

using System;
using System.Net.Http;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main(string[] args)
    {
        var client = new HttpClient();

        try
        {
            var response = await client.GetAsync("https://example.com");
            response.EnsureSuccessStatusCode();
            var content = await response.Content.ReadAsStringAsync();
            Console.WriteLine(content);
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"Request exception: {ex.Message}");
        }
    }
}

Snowflake error about SSL

These problems can occur in other packages that are built on top http client in Python or .NET or any other programming languages. For example, Snowflake python connector can raise issues like the following if the cert is not trusted:

snowflake.connector.errors.OperationalError: 25003: Failed to get the response. Hanging? method: post, url: https://***

In Snowflake .NET driver, similar exception can be raised:

Unhandled exception. Snowflake.Data.Client.SnowflakeDbException : Error: Snowflake Internal Error: Unable to connect. One or more errors occurred.

When looking into details, it usually involves errors like RemoteCerticateChainErrors.

Fix the problems

There are different ways to address these issues.

The right approach

The right approach is to get in touch your company IT network team and system administrators to use a valid certificate that is trusted by root so that as a system user you don't need to use workarounds as bypass SSL certificate verification can be very dangerous.

Tactical solutions

Sometimes, it might not be easy to apply a system wide fix or it takes time to implement. Hence you can use some workarounds to fix them in your application temporarily.

Consider the risk first

Before you take these tactical solutions, evaluate the risks and make sure you absolute trust the certificate returned from the proxy. Please note that it’s generally not recommended to disable SSL verification due to the security risks involved.

If you are comfortable with the cert, download and save it to your system. The following code snippets assume the cert is saved in path /path/to/public-key.pem.

Use environment variable REQUESTS_CA_BUNDLE

For Python, you can use environment variable REQUESTS_CA_BUNDLE to add this custom cert into Python's trusted certificate list.

import os
import requests

# Set the REQUESTS_CA_BUNDLE environment variable
os.environ['REQUESTS_CA_BUNDLE'] = '/path/to/your/certificate.pem'

# Now, requests will use the specified CA bundle for SSL verification
response = requests.get('https://example.com')

For all HTTPS requests, Python will trust this customized certificate.

Alternatively you can set it up when you run the scripts:

export REQUESTS_CA_BUNDLE=/path/to/your/certificate.pem
python script.py

For Python requests package

For requests initiated using Python requests package, you can directly specify it too instead of using the above environment variable.

import requests

url = 'https://example.com'
response = requests.get(url, verify='/path/to/public-key.pem')

For .NET applications

For .NET applications, there are no equivalent environment variables you can use. You have to install the cert into root trust store. If you cannot do that and if the cert itself cannot be verified or is invalid, you will have to bypass it using the following approach. 


You can bypass SSL certificate validation in .NET by using the HttpClientHandler.ServerCertificateCustomValidationCallback property. This property allows you to provide a custom validation callback that can ignore certificate errors. Here’s an example:

using System;
using System.Net.Http;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main(string[] args)
    {
        var handler = new HttpClientHandler();
        handler.ServerCertificateCustomValidationCallback = 
            (message, cert, chain, errors) => { return true; };

        var client = new HttpClient(handler);

        try
        {
            var response = await client.GetAsync("https://example.com");
            response.EnsureSuccessStatusCode();
            var content = await response.Content.ReadAsStringAsync();
            Console.WriteLine(content);
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"Request exception: {ex.Message}");
        }
    }
}

In the code above, the ServerCertificateCustomValidationCallback is set to a lambda function that always returns true, effectively ignoring any SSL certificate errors.

Please note that bypassing SSL certificate validation can pose a security risk, as it allows connections to servers with potentially untrusted or compromised certificates. This approach should only be used in controlled environments or for testing purposes.

Other thoughts

For certificates returned by SSL interception proxy server, they are usually have a short valid period. Hence, you will need to apply these solutions regularly until the proxy server can issue public certs that are automatically trusted by your applications.

More from Kontext
comment Comments
No comments yet.

Please log in or register to comment.

account_circle Log in person_add Register

Log in with external accounts