Обход недопустимого SSL-сертификата в ядре .net

Я работаю над проектом, который нужно подключить к сайту https. Каждый раз, когда я подключаюсь, мой код генерирует исключение, потому что сертификат этого сайта поступает с ненадежного сайта. Есть ли способ обойти проверку сертификата в .net core http?

Я видел этот код из предыдущей версии .NET. Думаю, мне просто нужно что-то вроде этого.

 ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;

Ответ 1

ServicePointManager.ServerCertificateValidationCallback не поддерживается в .Net Core.

Текущая ситуация заключается в том, что это будет новый метод ServerCertificateCustomValidationCallback для предстоящего контракта 4.1. * System.Net.Http(HttpClient). Команда .NET Core завершает работу с контрактом 4.1. Вы можете прочитать об этом в здесь, на github

Вы можете попробовать предварительную версию System.Net.Http 4.1, используя источники непосредственно здесь, в CoreFx или в канале MYGET: https://dotnet.myget.org/gallery/dotnet-core

Текущее определение WinHttpHandler.ServerCertificateCustomValidationCallback в Github

Ответ 2

Вы можете переопределить проверку сертификата SSL на HTTP-вызов с помощью функции анонимного обратного вызова, например

using (var httpClientHandler = new HttpClientHandler())
{
   httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
   using (var client = new HttpClient(httpClientHandler))
   {
       // Make your request...
   }
}

Кроме того, я предлагаю использовать шаблон factory для HttpClient, потому что это общий объект, который не может быть удален сразу, и поэтому соединения будут оставаться открытая.

Ответ 3

Пришел сюда искать ответ на ту же проблему, но я использую WCF для NET Core. Если вы находитесь в одной лодке, используйте:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = 
    new X509ServiceCertificateAuthentication()
    {
        CertificateValidationMode = X509CertificateValidationMode.None,
        RevocationMode = X509RevocationMode.NoCheck
    };

Ответ 4

Я решаю с этим:

Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpClient("HttpClientWithSSLUntrusted").ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
        {
            ClientCertificateOptions = ClientCertificateOption.Manual,
            ServerCertificateCustomValidationCallback =
            (httpRequestMessage, cert, cetChain, policyErrors) =>
            {
                return true;
            }
        });

YourService.cs

public UserService(IHttpClientFactory clientFactory, IOptions<AppSettings> appSettings)
    {
        _appSettings = appSettings.Value;
        _clientFactory = clientFactory;
    }

var request = new HttpRequestMessage(...

var client = _clientFactory.CreateClient("HttpClientWithSSLUntrusted");

HttpResponseMessage response = await client.SendAsync(request);

Ответ 5

Я столкнулся с той же проблемой при работе с самоподписанными сертификатами и аутентификацией сертификата клиента в контейнерах .NET Core 2.2 и Docker Linux. Все отлично работало на моем компьютере с Windows, но в Docker я получил такую ошибку:

System.Security.Authentication.AuthenticationException: удаленный сертификат недействителен в соответствии с процедурой проверки

К счастью, сертификат был создан с использованием цепочки. Конечно, вы всегда можете игнорировать это решение и использовать вышеуказанные решения.

Итак, вот мое решение:

  1. Я сохранил сертификат с помощью Chrome на своем компьютере в формате P7B.

  2. Преобразуйте сертификат в формат PEM с помощью этой команды:
    openssl pkcs7 -inform DER -outform PEM -in <cert>.p7b -print_certs > ca_bundle.crt

  3. Откройте файл ca_bundle.crt и удалите все записи Subject, оставив чистый файл. Пример ниже:

    -----BEGIN CERTIFICATE-----
    _BASE64 DATA_
    -----END CERTIFICATE-----
    -----BEGIN CERTIFICATE-----
    _BASE64 DATA_
    -----END CERTIFICATE-----
    -----BEGIN CERTIFICATE-----
    _BASE64 DATA_
    -----END CERTIFICATE-----
  1. Поместите эти строки в Dockerfile (на последних шагах):
    # Update system and install curl and ca-certificates
    RUN apt-get update && apt-get install -y curl && apt-get install -y ca-certificates
    # Copy your bundle file to the system trusted storage
    COPY ./ca_bundle.crt /usr/local/share/ca-certificates/ca_bundle.crt
    # During docker build, after this line you will get such output: 1 added, 0 removed; done.
    RUN update-ca-certificates
  1. В приложении:
    var address = new EndpointAddress("https://serviceUrl");                
    var binding = new BasicHttpsBinding
    {
        CloseTimeout = new TimeSpan(0, 1, 0),
        OpenTimeout = new TimeSpan(0, 1, 0),
        ReceiveTimeout = new TimeSpan(0, 1, 0),
        SendTimeout = new TimeSpan(0, 1, 0),
        MaxBufferPoolSize = 524288,
        MaxBufferSize = 65536,
        MaxReceivedMessageSize = 65536,
        TextEncoding = Encoding.UTF8,
        TransferMode = TransferMode.Buffered,
        UseDefaultWebProxy = true,
        AllowCookies = false,
        BypassProxyOnLocal = false,
        ReaderQuotas = XmlDictionaryReaderQuotas.Max,
        Security =
        {
            Mode = BasicHttpsSecurityMode.Transport,
            Transport = new HttpTransportSecurity
            {
                ClientCredentialType = HttpClientCredentialType.Certificate,
                ProxyCredentialType = HttpProxyCredentialType.None
            }
        }
    };
    var client = new MyWSClient(binding, address);
    client.ClientCredentials.ClientCertificate.Certificate = GetClientCertificate("clientCert.pfx", "passwordForClientCert");
    // Client certs must be installed
    client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication
    {
        CertificateValidationMode = X509CertificateValidationMode.ChainTrust,
        TrustedStoreLocation = StoreLocation.LocalMachine,
        RevocationMode = X509RevocationMode.NoCheck
    };

Метод GetClientCertificate:

private static X509Certificate2 GetClientCertificate(string clientCertName, string password)
{
    //Create X509Certificate2 object from .pfx file
    byte[] rawData = null;
    using (var f = new FileStream(Path.Combine(AppContext.BaseDirectory, clientCertName), FileMode.Open, FileAccess.Read))
    {
        var size = (int)f.Length;
        var rawData = new byte[size];
        f.Read(rawData, 0, size);
        f.Close();
    }
    return new X509Certificate2(rawData, password);
}

Ответ 6

В .NetCore вы можете добавить следующий фрагмент кода в методе настройки служб. Я добавил проверку, чтобы убедиться, что мы пропускаем SSL-сертификат только в среде разработки

services.AddHttpClient("HttpClientName", client => {
// code to configure headers etc..
}).ConfigurePrimaryHttpMessageHandler(() => {
                  var handler = new HttpClientHandler();
                  if (hostingEnvironment.IsDevelopment())
                  {
                      handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
                  }
                  return handler;
              });

Ответ 7

Да, откройте приложение до любого хакера. Отличная идея. Мне понадобится около двух минут, чтобы создать поддельный сертификат для любого сайта (со встроенной функциональностью MacOS X, скорее всего, доступной как в Windows, так и в Linux, а также в аналогичной форме). Перенаправление вашего сайта требует хакера немного дольше, но это не проблема.

Если у сайта есть сломанный или устаревший сертификат, вы переходите к администратору сайта, даете ему хороший пинок и говорите ему, чтобы он исправил свой сайт. Ни при каких обстоятельствах вы даже не должны рассматривать использование https со сломанным сертификатом.