SSL olduğunda sertifika kontrolü nasıl göz ardı edilir


132

Bir Https kaynağı talep ettiğimde sertifika kontrolünü göz ardı etmenin bir yolunu bulmaya çalışıyorum, şimdiye kadar internette bazı yararlı makaleler buldum.

Ama hala bir sorunum var. Lütfen kodumu gözden geçirin. Kodun ne anlama geldiğini anlamıyorum ServicePointManager.ServerCertificateValidationCallback.

Bu temsilci yöntemi ne zaman çağrılacak? Ve bir soru daha, bu kodu hangi yere yazmalıyım? Önce ServicePointManager.ServerCertificateValidationCallbackçalıştırmak veya daha önce Stream stream = request.GetRequestStream()?

public HttpWebRequest GetRequest()
{
    CookieContainer cookieContainer = new CookieContainer();

    // Create a request to the server
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_remoteUrl);

    #region Set request parameters

    request.Method = _context.Request.HttpMethod;
    request.UserAgent = _context.Request.UserAgent;
    request.KeepAlive = true;
    request.CookieContainer = cookieContainer;
    request.PreAuthenticate = true;
    request.AllowAutoRedirect = false;

    #endregion

    // For POST, write the post data extracted from the incoming request
    if (request.Method == "POST")
    {
        Stream clientStream = _context.Request.InputStream;
        request.ContentType = _context.Request.ContentType;
        request.ContentLength = clientStream.Length;

        ServicePointManager.ServerCertificateValidationCallback = delegate(
            Object obj, X509Certificate certificate, X509Chain chain, 
            SslPolicyErrors errors)
            {
                return (true);
            };

            Stream stream = request.GetRequestStream();

            ....
        }

        ....

        return request;
    }
}   

Olası C #
Matyas

Yanıtlar:


67

Sadece bir küresel olmadığı ServicePointManager , ayar ServicePointManager.ServerCertificateValidationCallback sonraki tüm istekleri bu politikayı devralan olacağı sonucu verecektir. Global bir "ayar" olduğu için Global.asax içindeki Application_Start yönteminde ayarlanması tercih edilir .

Geri aramayı ayarlamak, varsayılan davranışı geçersiz kılar ve kendiniz özel bir doğrulama rutini oluşturabilirsiniz.


Global.asax'ı olmayan bir müşteri için ne olacak? Elde taşınan bir cihazdan yerel ağda çalışan bir REST servisini arıyorum.
B. Clay Shannon

3
Soru özeldir HttpWebRequest. Başka bir yol kullanıyorsanız, bunu nasıl yapacağınıza dair belgelere bakmanız gerekir.
Sani Singh Huttunen

HttpWebRequest'e dönüştürülen WebRequest'i kullanıyorum, örneğin: ((HttpWebRequest) request) .Accept = contentType;
B. Clay Shannon

Cevabımda belirtildiği gibi: Global.asax içinde ayarlamak TERCİH EDİLİR. REST servisini aramadan önce bile ayarlayabilirsiniz.
Sani Singh Huttunen

3
Olası bir çözüm için bu bağlantıya bakın .
Sani Singh Huttunen

174

Bu çözümü istek bazında uygulamak isteyen herkes için bu bir seçenektir ve bir Lambda ifadesi kullanır. Aynı Lambda ifadesi, blak3r tarafından bahsedilen genel filtreye de uygulanabilir. Bu yöntem .NET 4.5 gerektiriyor gibi görünüyor.

String url = "https://www.stackoverflow.com";
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

.NET 4.0'da, Lambda İfadesi genel filtreye bu şekilde uygulanabilir

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

2
FtpWebRequest için istek başına herhangi bir çözüm var mı?
Timo

4.0
Nacht

Elbette neden isteyeceğinizi anlayabilsem de, 'küresel' varyant için çok daha güzel bir çözüm olduğunu düşünüyorum. Şahsen ben, daha sonra bu doğrulama geri aramasını yöneten bir talep fabrikasını tercih ediyorum. Teşekkürler Adam, güzel çözüm.
Senatör

2
Geri dönmek true, geliştirme sırasında deney yaparken yapabileceğiniz bir şeydir, ancak güvensizdir. Koşullu olmalı.
Fred

1
Kullanımı (HttpWebRequest)WebRequest.Create(url)tamamen geçerli, ancak benim kutumda, HttpWebRequest.Create(url).Net 4.6.2'yi hedefleyen bir projede hala var. Şefin seçimi, ancak bu noktada HttpClientmuhtemelen kullanılacak daha iyi API.
Adam Venezia

53

Bu benim için çalıştı:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                        System.Security.Cryptography.X509Certificates.X509Chain chain,
                        System.Net.Security.SslPolicyErrors sslPolicyErrors)
    {
        return true; // **** Always accept
    };

Snippet buradan: http://www.west-wind.com/weblog/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors


17
ServicePointManager.ServerCertificateValidationCallback + = (gönderen, sertifika, zincir, sslPolicyErrors) => true;
David Rutgos

3
Her zaman doğruyu döndürmek güvensizdir. Koşullu olarak doğruya dönmelidir.
Fred

Bu işlem başına olduğundan güvenli değildir.
Mikhail Orlov

25

Ayrıca kısa delege çözümü var:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 

3
Her zaman geri dönmek truegüvensizdir.
Fred

7
Evet, her zaman tüm SSL sertifikalarına güvenmek tanımı gereği güvensizdir. Mümkünse bunu yapmaktan kaçının.
Andrej Rommel

@AndrejRommel sizin yolunuz ne tavsiye edilir?
Kiquenet

2
Önerilen yol, geçerli bir SSL sertifikası oluşturmak ve sunucu üzerinde kontrolünüz varsa bunu doğru şekilde kullanmaktır. Letsencrypt.org'u kullanarak bir tane oluşturduk.
Andrej Rommel

5

NET 4.5'ten önce özelliğin, kendisine erişme isteği üzerine ServicePointManager kullanılamadığı belirtildi.

İşte size ServicePointistek başına temelinde erişmenizi sağlayacak .NET 4.0 kodu . Size istek başına geri aramaya erişim sağlamaz, ancak sorunla ilgili daha fazla ayrıntı bulmanızı sağlar. Sadece scvPoint.Certificate(veya ClientCertificatetercih ederseniz) özelliklere erişin .

WebRequest request = WebRequest.Create(uri);

// oddity: these two .Address values are not necessarily the same!
//  The service point appears to be related to the .Host, not the Uri itself.
//  So, check the .Host vlaues before fussing in the debugger.
//
ServicePoint svcPoint = ServicePointManager.FindServicePoint(uri);
if (null != svcPoint)
{
    if (!request.RequestUri.Host.Equals(svcPoint.Address.Host, StringComparison.OrdinalIgnoreCase))
    {
        Debug.WriteLine(".Address              == " + request.RequestUri.ToString());
        Debug.WriteLine(".ServicePoint.Address == " + svcPoint.Address.ToString());
    }
    Debug.WriteLine(".IssuerName           == " + svcPoint.Certificate.GetIssuerName());
}

Kabul! Ama sonra, bu OP ignoreonlara nasıl güvenecekleri ile ilgilidir, onlara güvenmekle değil.
Jesse Chisholm

Neyse, kullanma ServicePointben olamaz hep güvenen tüm SSL sertifikaları, ne Tüm sertifikaları görmezden vermemiş ServerCertificateValidationCallback ServicePoint içinde temsilci
Kiquenet

4

Sadece tesadüfen, bu, bildiğim belirli bir uygulamadaki tüm sertifika doğrulamasını kapatmanın en az ayrıntılı bir yoludur:

ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;

4

ServicePointManager'a sertifika doğrulamasını genel olarak geçersiz kılacak bir geri arama eklemek yerine, geri aramayı yerel bir HttpClient örneğinde ayarlayabilirsiniz. Bu yaklaşım yalnızca bu HttpClient örneği kullanılarak yapılan çağrıları etkilemelidir.

Belirli sunucular için sertifika doğrulama hatalarının yok sayılmasının bir Web API denetleyicisinde nasıl uygulanabileceğini gösteren örnek kod aşağıda verilmiştir.

using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

public class MyController : ApiController
{

    // use this HttpClient instance when making calls that need cert errors suppressed
    private static readonly HttpClient httpClient;

    static MyController()
    {
        // create a separate handler for use in this controller
        var handler = new HttpClientHandler();

        // add a custom certificate validation callback to the handler
        handler.ServerCertificateCustomValidationCallback = ((sender, cert, chain, errors) => ValidateCert(sender, cert, chain, errors));

        // create an HttpClient that will use the handler
        httpClient = new HttpClient(handler);
    }

    protected static ValidateCert(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors)
    {

        // set a list of servers for which cert validation errors will be ignored
        var overrideCerts = new string[]
        {
            "myproblemserver",
            "someotherserver",
            "localhost"
        };

        // if the server is in the override list, then ignore any validation errors
        var serverName = cert.Subject.ToLower();
        if (overrideCerts.Any(overrideName => serverName.Contains(overrideName))) return true;

        // otherwise use the standard validation results
        return errors == SslPolicyErrors.None;
    }

}

Bu sadece .NET Core için çalışmayacak mı? (Veya ServerCertificateCustomValidationCallback HttpClientHandler'a her eklendiğinde)?
phillyslick

Bu çözüm .Net Framework 4.5 ve sonrasında ve .Net Core'da çalışmalıdır (.Net Core'da test etmemiş olmama rağmen).
Sheldon

@Sheldon, bu bir mücevherdi :) localhost api aramalarında .net ve .net core uygulaması arasında başarıyla kullanıldı. Hepsini kabul etmeden güzel bir çözüm.
Büyük

3

Adam'ın cevabına ve Rob'un yorumuna dayanarak şunu kullandım:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => certificate.Issuer == "CN=localhost";

bu da "görmezden gelme" yi bir şekilde filtreler. Elbette gerektiği gibi başka ihraççılar da eklenebilir. Bazı eski kodları desteklememiz gerektiğinden, bu .NET 2.0'da test edilmiştir.


@karank Geç cevap için özür dilerim - Asıl aramadan önce herhangi bir yere eklenebilir, örn. request.GetResponse () çağrılmadan önce. İhraççı'nın sizin durumunuzda başka bir şey içerebileceğini unutmayın.
Andrej Grobler

3

CA5386: Güvenlik açığı analiz araçları sizi bu kodlar konusunda uyaracaktır.

Doğru kod:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) =>
{
   return (sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) != SslPolicyErrors.RemoteCertificateNotAvailable;
};

3

.Net çekirdeği için

using (var handler = new HttpClientHandler())
{ 
    // allow the bad certificate
    handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => true;
    using (var httpClient = new HttpClient(handler))
    {
        await httpClient.PostAsync("the_url", null);
    }
}

2

Açıkça ifade edildi ...

ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(CertCheck);

private static bool CertCheck(object sender, X509Certificate cert,
X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
    return true;
}

0

Sani'nin ve blak3r'ın yanıtlarına ek olarak, uygulamamın başlangıç ​​koduna aşağıdakileri ekledim, ancak VB'de:

'** Overriding the certificate validation check.
Net.ServicePointManager.ServerCertificateValidationCallback = Function(sender, certificate, chain, sslPolicyErrors) True

Hile yapıyor gibi görünüyor.


0

İpucu: Bu yöntemi, yakında sona erecek olan sertifikaları izlemek için de kullanabilirsiniz. Bu, süresi dolmak üzere olan bir sertifika bulursanız pastırmanızı kaydedebilir ve zamanında düzeltebilir. Üçüncü şahıs şirketler için de iyi - bizim için bu DHL / FedEx. DHL, Şükran Günü'nden 3 gün önce bizi alt üst eden sertifikanın süresinin dolmasına izin verdi. Neyse ki düzeltmek üzereyim ... bu sefer!

    private static DateTime? _nextCertWarning;
    private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
    {
        if (error == SslPolicyErrors.None)
        {
            var cert2 = cert as X509Certificate2;
            if (cert2 != null)
            { 
                // If cert expires within 2 days send an alert every 2 hours
                if (cert2.NotAfter.AddDays(-2) < DateTime.Now)
                {
                    if (_nextCertWarning == null || _nextCertWarning < DateTime.Now)
                    {
                        _nextCertWarning = DateTime.Now.AddHours(2);

                        ProwlUtil.StepReached("CERT EXPIRING WITHIN 2 DAYS " + cert, cert.GetCertHashString());   // this is my own function
                    }
                }
            }

            return true;
        }
        else
        {
            switch (cert.GetCertHashString())
            {
                // Machine certs - SELF SIGNED
                case "066CF9CAD814DE2097D367F22D3A7E398B87C4D6":    

                    return true;

                default:
                    ProwlUtil.StepReached("UNTRUSTED CERT " + cert, cert.GetCertHashString());
                    return false;
            }
        }
    }

Uyarı mekanizmanızın süresi dolmuş bir sertifikaya sahip olabileceği durumu hallettiğinizden emin olun - yoksa bir yığın akışı ile sonuçlanırsınız!
Simon_Weaver

Nedir ProwlUtil.StepReached?
Kiquenet

Maalesef bu, telefonuma bildirim gönderebilen Prowl API'yi çağırmak için kendi yöntemim. Ancak oturum açmak istiyorsanız, bu iyidir. Bunun gibi şeyler için telefonumda dinlenmeyi seviyorum!
Simon_Weaver

0

Yukarıdaki birkaç cevap işe yarar. Kod değişiklikleri yapmaya devam etmek zorunda olmadığım ve kodumu güvensiz hale getirmediğim bir yaklaşım istedim. Bu nedenle bir beyaz liste oluşturdum. Beyaz liste herhangi bir veri deposunda tutulabilir. Çok küçük bir liste olduğu için yapılandırma dosyasını kullandım.

Kodum aşağıda.

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) => {
    return error == System.Net.Security.SslPolicyErrors.None || certificateWhitelist.Contains(cert.GetCertHashString());
};

0

Bu çözümün Unity C # sürümü:

void Awake()
{
    System.Net.ServicePointManager.ServerCertificateValidationCallback += ValidateCertification;
}

void OnDestroy()
{
    ServerCertificateValidationCallback = null;
}

public static bool ValidateCertification(object sender, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
    return true;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.