C # Ignorować błędy certyfikatów?

159

Otrzymuję następujący błąd podczas żądania usługi sieciowej do zdalnej usługi internetowej:

Nie można ustanowić relacji zaufania dla bezpiecznego kanału SSL / TLS. ---> System.Security.Authentication.AuthenticationException: zdalny certyfikat jest nieprawidłowy zgodnie z procedurą sprawdzania poprawności.

Czy mimo wszystko można zignorować ten błąd i kontynuować?

Wygląda na to, że zdalny certyfikat nie jest podpisany.

Witryna, z którą się łączę, to www.czebox.cz- więc nie krępuj się jej odwiedzić i zauważ, że nawet przeglądarki generują wyjątki bezpieczeństwa.

J L.
źródło

Odpowiedzi:

341

Dodaj moduł obsługi walidacji certyfikatu. Zwrot truepozwoli zignorować błąd walidacji:

ServicePointManager
    .ServerCertificateValidationCallback += 
    (sender, cert, chain, sslPolicyErrors) => true;
Peter Lillevold
źródło
6
Jest to nawet bardziej przydatne niż mogłoby się wydawać. Napotkałem problem OP podczas korzystania z Managed Exchanged Web Services (EWS). Pomyślałem, że nie mogę użyć tej odpowiedzi, ponieważ nie mam dostępu do wywołań SOAP niskiego poziomu, które są wykonywane przez tę zarządzaną bibliotekę. Ale kiedy przyjrzałem się temu raz jeszcze, zdałem sobie sprawę, że ServicePointManager stoi sam. Więc dodałem powyższe wywołanie zwrotne przed zainicjowaniem ExchangeService i działało to jak urok.
Mark Meuer
2
Oto przykład globalnego zastosowania obejścia. Dla nas wszystkich w złe praktyki. (Czasami nie masz wyboru) jasig.275507.n4.nabble.com/…
snowYetis
1
wielkie dzięki to tymczasowo rozwiązuje problem. Dodaj ten kod w Startup.cs w Web Api
Sivalingaamorthy
2
@MarkMeuer prawie zamierzał zrezygnować z tego rozwiązania z powodu mojego problemu z EWS API, ale wtedy zobaczyłem twój komentarz.
Mahen
7
@MiguelVeloso możesz oczywiście przegłosować, ale pamiętaj, że ani pytanie, ani odpowiedź nie dotyczą bezpieczeństwa. Temat wyraźnie dotyczy „jak zignorować błąd walidacji”, a nie „dlaczego powinniśmy / nie robić”, co jest zupełnie innym tematem. Wchodzenie w dyskusję na temat tego, dlaczego PO nie powinien tego robić, tylko zamuliłoby wody, jak zauważyli komentatorzy, istnieją rozsądne przypadki, w których faktycznie byś to zrobił. Trzymamy się więc tematu i rozwiązujemy problem.
Peter Lillevold
40

Zezwalanie na wszystkie certyfikaty jest bardzo potężne, ale może być również niebezpieczne. Jeśli chcesz zezwolić tylko na ważne certyfikaty i niektóre określone certyfikaty, możesz to zrobić w ten sposób.

.NET core:

using (var httpClientHandler = new HttpClientHandler())
{
    httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => {
        if (sslPolicyErrors == SslPolicyErrors.None)
        {
            return true;   //Is valid
        }

        if (cert.GetCertHashString() == "99E92D8447AEF30483B1D7527812C9B7B3A915A7")
        {
            return true;
        }
        return false;
    };
    using (var httpClient = new HttpClient(httpClientHandler))
    {
        var httpResponse = httpClient.GetAsync("https://example.com").Result;
    }
}

.NET Framework:

System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate (
    object sender,
    X509Certificate cert,
    X509Chain chain,
    SslPolicyErrors sslPolicyErrors)
{
    if (sslPolicyErrors == SslPolicyErrors.None)
    {
        return true;   //Is valid
    }

    if (cert.GetCertHashString() == "99E92D8447AEF30483B1D7527812C9B7B3A915A7")
    {
        return true;
    }

    return false;
};

Aktualizacja:

Jak uzyskać cert.GetCertHashString()wartość w Chrome:

Kliknij Securelub Not Securena pasku adresu.

wprowadź opis obrazu tutaj

wprowadź opis obrazu tutaj

Następnie kliknij Certyfikat -> Szczegóły -> Odcisk palca i skopiuj wartość. Pamiętaj o tym cert.GetCertHashString().ToLower().

wprowadź opis obrazu tutaj

Ogglas
źródło
3
@MiguelVeloso Całkowicie się zgadzam. Pozwala to na pominięcie sprawdzania (miejmy nadzieję) jednego lub dwóch certyfikatów bez całkowitego narażania bezpieczeństwa.
Kemuel Sanchez
JAK mogę uzyskać Hash Stringod certyfikatu?
Kiquenet
@Kiquenet Albo debugowania kodu i uruchomić cert.GetCertHashString()z Immediate windowlub sprawdź cert Thumbprintw przeglądarce lub MMCjeżeli jest on zainstalowany lokalnie.
Ogglas
Serwer jest pod naszą kontrolą, czy nadal można bezpiecznie używać kodu @ Ogglas na produkcji? Czy przy użyciu protokołu TLS / SSL można powstrzymać ataki typu man-in-the-middle?
Pingpong
Dziękuję bardzo za wielką pomoc.
Wowo Ot
30

Metoda IgnoreBadCertificates:

//I use a method to ignore bad certs caused by misc errors
IgnoreBadCertificates();

// after the Ignore call i can do what ever i want...
HttpWebRequest request_data = System.Net.WebRequest.Create(urlquerystring) as HttpWebRequest;

/*
and below the Methods we are using...
*/

/// <summary>
/// Together with the AcceptAllCertifications method right
/// below this causes to bypass errors caused by SLL-Errors.
/// </summary>
public static void IgnoreBadCertificates()
{
    System.Net.ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);
}  

/// <summary>
/// In Short: the Method solves the Problem of broken Certificates.
/// Sometime when requesting Data and the sending Webserverconnection
/// is based on a SSL Connection, an Error is caused by Servers whoes
/// Certificate(s) have Errors. Like when the Cert is out of date
/// and much more... So at this point when calling the method,
/// this behaviour is prevented
/// </summary>
/// <param name="sender"></param>
/// <param name="certification"></param>
/// <param name="chain"></param>
/// <param name="sslPolicyErrors"></param>
/// <returns>true</returns>
private static bool AcceptAllCertifications(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certification, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
    return true;
} 
Amen Ra
źródło
2
Musiałem dodać jeszcze jedną linię, aby to działało z moim kodem (używam websocket4net). System.Net.ServicePointManager.CheckCertificateRevocationList = false; Zaraz po ustawieniu wywołania zwrotnego weryfikacji certyfikatu serwera.
kalyanswaroop
24

Przyczyną niepowodzenia nie jest to, że nie jest podpisany, ale dlatego, że certyfikat główny nie jest zaufany przez klienta. Zamiast wyłączać sprawdzanie poprawności SSL, alternatywnym podejściem byłoby dodanie certyfikatu głównego urzędu certyfikacji do listy urzędów certyfikacji, którym ufa Twoja aplikacja.

To jest główny certyfikat urzędu certyfikacji, któremu Twoja aplikacja obecnie nie ufa:

-----BEGIN CERTIFICATE-----
MIIFnDCCBISgAwIBAgIBZDANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJDWjEs
MCoGA1UECgwjxIxlc2vDoSBwb8WhdGEsIHMucC4gW0nEjCA0NzExNDk4M10xHjAc
BgNVBAMTFVBvc3RTaWdudW0gUm9vdCBRQ0EgMjAeFw0xMDAxMTkwODA0MzFaFw0y
NTAxMTkwODA0MzFaMFsxCzAJBgNVBAYTAkNaMSwwKgYDVQQKDCPEjGVza8OhIHBv
xaF0YSwgcy5wLiBbScSMIDQ3MTE0OTgzXTEeMBwGA1UEAxMVUG9zdFNpZ251bSBS
b290IFFDQSAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoFz8yBxf
2gf1uN0GGXknvGHwurpp4Lw3ZPWZB6nEBDGjSGIXK0Or6Xa3ZT+tVDTeUUjT133G
7Vs51D6z/ShWy+9T7a1f6XInakewyFj8PT0EdZ4tAybNYdEUO/dShg2WvUyfZfXH
0jmmZm6qUDy0VfKQfiyWchQRi/Ax6zXaU2+X3hXBfvRMr5l6zgxYVATEyxCfOLM9
a5U6lhpyCDf2Gg6dPc5Cy6QwYGGpYER1fzLGsN9stdutkwlP13DHU1Sp6W5ywtfL
owYaV1bqOOdARbAoJ7q8LO6EBjyIVr03mFusPaMCOzcEn3zL5XafknM36Vqtdmqz
iWR+3URAUgqE0wIDAQABo4ICaTCCAmUwgaUGA1UdHwSBnTCBmjAxoC+gLYYraHR0
cDovL3d3dy5wb3N0c2lnbnVtLmN6L2NybC9wc3Jvb3RxY2EyLmNybDAyoDCgLoYs
aHR0cDovL3d3dzIucG9zdHNpZ251bS5jei9jcmwvcHNyb290cWNhMi5jcmwwMaAv
oC2GK2h0dHA6Ly9wb3N0c2lnbnVtLnR0Yy5jei9jcmwvcHNyb290cWNhMi5jcmww
gfEGA1UdIASB6TCB5jCB4wYEVR0gADCB2jCB1wYIKwYBBQUHAgIwgcoagcdUZW50
byBrdmFsaWZpa292YW55IHN5c3RlbW92eSBjZXJ0aWZpa2F0IGJ5bCB2eWRhbiBw
b2RsZSB6YWtvbmEgMjI3LzIwMDBTYi4gYSBuYXZhem55Y2ggcHJlZHBpc3UvVGhp
cyBxdWFsaWZpZWQgc3lzdGVtIGNlcnRpZmljYXRlIHdhcyBpc3N1ZWQgYWNjb3Jk
aW5nIHRvIExhdyBObyAyMjcvMjAwMENvbGwuIGFuZCByZWxhdGVkIHJlZ3VsYXRp
b25zMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQW
BBQVKYzFRWmruLPD6v5LuDHY3PDndjCBgwYDVR0jBHwweoAUFSmMxUVpq7izw+r+
S7gx2Nzw53ahX6RdMFsxCzAJBgNVBAYTAkNaMSwwKgYDVQQKDCPEjGVza8OhIHBv
xaF0YSwgcy5wLiBbScSMIDQ3MTE0OTgzXTEeMBwGA1UEAxMVUG9zdFNpZ251bSBS
b290IFFDQSAyggFkMA0GCSqGSIb3DQEBCwUAA4IBAQBeKtoLQKFqWJEgLNxPbQNN
5OTjbpOTEEkq2jFI0tUhtRx//6zwuqJCzfO/KqggUrHBca+GV/qXcNzNAlytyM71
fMv/VwgL9gBHTN/IFIw100JbciI23yFQTdF/UoEfK/m+IFfirxSRi8LRERdXHTEb
vwxMXIzZVXloWvX64UwWtf4Tvw5bAoPj0O1Z2ly4aMTAT2a+y+z184UhuZ/oGyMw
eIakmFM7M7RrNki507jiSLTzuaFMCpyWOX7ULIhzY6xKdm5iQLjTvExn2JTvVChF
Y+jUu/G0zAdLyeU4vaXdQm1A8AEiJPTd0Z9LAxL6Sq2iraLNN36+NyEK/ts3mPLL

-----END CERTIFICATE-----

Możesz zdekodować i wyświetlić ten certyfikat za pomocą

ten dekoder certyfikatu lub inny dekoder certyfikatu

bignum
źródło
Tak! Tak jest w moim przypadku, ale jak mogę dodać certyfikat na platformie Azure bez maszyny wirtualnej? Czy mogę po prostu użyć interfejsu API X509Store? Spróbuję tego jutro, ale wszelkie informacje są mile widziane
João Antunes
7

Aby wyłączyć sprawdzanie poprawności certyfikatu SSL w konfiguracji klienta.

<behaviors>
   <endpointBehaviors>
      <behavior name="DisableSSLCertificateValidation">
         <clientCredentials>
             <serviceCertificate>
                <sslCertificateAuthentication certificateValidationMode="None" />
              </serviceCertificate>
           </clientCredentials>
        </behavior>
d.marzo
źródło
Czy to jest plik web.config ? Jakieś alternatywy dla ASP.NET Core?
Shimmy Weitzhandler
5

Ten kod zadziałał dla mnie. Musiałem dodać TLS2, ponieważ właśnie tego interesuje mnie URL.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback +=
    (sender, cert, chain, sslPolicyErrors) => { return true; };
using (var client = new HttpClient())
{
    client.BaseAddress = new Uri(UserDataUrl);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new
      MediaTypeWithQualityHeaderValue("application/json"));
    Task<string> response = client.GetStringAsync(UserDataUrl);
    response.Wait();

    if (response.Exception != null)
    {
         return null;
    }

    return JsonConvert.DeserializeObject<UserData>(response.Result);
}
user2347528
źródło
3

Omiń certyfikat SSL ...

        HttpClientHandler clientHandler = new HttpClientHandler();
        clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };

        // Pass the handler to httpclient(from you are calling api)
        var client = new HttpClient(clientHandler)
Rohit Jangid
źródło
2

Jeśli używasz gniazd bezpośrednio i uwierzytelniasz się jako klient, metoda wywołania zwrotnego programu Service Point Manager nie będzie działać. Oto, co zadziałało dla mnie. UŻYWAĆ WYŁĄCZNIE W CELACH TESTOWYCH .

var activeStream = new SslStream(networkStream, false, (a, b, c, d) => { return true; });
await activeStream.AuthenticateAsClientAsync("computer.local");

Kluczem jest tutaj zapewnienie zdalnego wywołania zwrotnego weryfikacji certyfikatu bezpośrednio w konstruktorze strumienia SSL.

Mario
źródło
1

Aby dalej rozwinąć post BIGNUM - najlepiej byłoby, gdybyś potrzebował rozwiązania, które będzie symulować warunki, które zobaczysz w środowisku produkcyjnym, a modyfikowanie kodu tego nie zrobi i może być niebezpieczne, jeśli zapomnisz wyjąć kod przed jego wdrożeniem.

Będziesz potrzebował jakiegoś certyfikatu z podpisem własnym. Jeśli wiesz, co robisz, możesz skorzystać z opublikowanego binarnego BIGNUM, ale jeśli nie, możesz poszukać certyfikatu. Jeśli używasz IIS Express, będziesz już mieć jeden z nich, po prostu musisz go znaleźć. Otwórz Firefoksa lub dowolną przeglądarkę, którą lubisz i przejdź do witryny deweloperskiej. Powinno być możliwe wyświetlenie informacji o certyfikacie z paska adresu URL, aw zależności od przeglądarki powinno być możliwe wyeksportowanie certyfikatu do pliku.

Następnie otwórz MMC.exe i dodaj przystawkę Certyfikat. Zaimportuj plik certyfikatu do magazynu zaufanych głównych urzędów certyfikacji i to wszystko, czego potrzebujesz. Ważne jest, aby upewnić się, że trafia do tego sklepu, a nie do innego sklepu, takiego jak „Osobisty”. Jeśli nie znasz programu MMC lub certyfikatów, istnieje wiele witryn internetowych zawierających informacje, jak to zrobić.

Teraz twój komputer jako całość będzie niejawnie ufał wszystkim certyfikatom, które sam wygenerował i nie będziesz musiał dodawać kodu, aby to obsłużyć. Kiedy przejdziesz do produkcji, będzie ona nadal działać, pod warunkiem, że masz tam zainstalowany odpowiedni ważny certyfikat. Nie rób tego na serwerze produkcyjnym - byłoby to złe i nie zadziała dla żadnych innych klientów poza tymi na samym serwerze.

Nigel Thomas
źródło
1

Działa to w przypadku platformy .Net Core. Zadzwoń do swojego klienta Soap:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
                new X509ServiceCertificateAuthentication()
                {
                    CertificateValidationMode = X509CertificateValidationMode.None,
                    RevocationMode = X509RevocationMode.NoCheck
                };  
Rimi
źródło