So ignorieren Sie die Zertifikatsprüfung bei ssl

132

Ich versuche einen Weg zu finden, die Zertifikatsprüfung zu ignorieren, wenn eine HTTP-Ressource angefordert wird. Bisher habe ich einen hilfreichen Artikel im Internet gefunden.

Aber ich habe immer noch ein Problem. Bitte überprüfen Sie meinen Code. Ich verstehe einfach nicht, was der Code ServicePointManager.ServerCertificateValidationCallbackbedeutet.

Wann wird diese Delegatmethode aufgerufen? Und noch eine Frage, an welcher Stelle soll ich diesen Code schreiben? Vor ServicePointManager.ServerCertificateValidationCallbackoder vor der Ausführung 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;
    }
}   
Joe.wang
quelle
Mögliches Duplikat von C # Zertifikatfehler ignorieren?
Matyas

Antworten:

67

Da es nur einen globalen ServicePointManager gibt , führt das Festlegen von ServicePointManager.ServerCertificateValidationCallback dazu, dass alle nachfolgenden Anforderungen diese Richtlinie erben. Da es sich um eine globale "Einstellung" handelt, ist es vorzuziehen , sie in der Application_Start- Methode in Global.asax festzulegen .

Durch Festlegen des Rückrufs wird das Standardverhalten überschrieben, und Sie können selbst eine benutzerdefinierte Validierungsroutine erstellen.

Sani Singh Huttunen
quelle
Was ist mit einem Kunden ohne Global.asax? Ich rufe einen REST-Dienst auf, der im lokalen Netzwerk von einem Handheld-Gerät ausgeführt wird.
B. Clay Shannon
3
Die Frage ist spezifisch für HttpWebRequest. Wenn Sie andere Mittel verwenden, müssen Sie in der Dokumentation nachsehen, wie dies erreicht werden kann.
Sani Singh Huttunen
Ich verwende WebRequest, das in HttpWebRequest umgewandelt wird, z. B.: ((HttpWebRequest) request) .Accept = contentType;
B. Clay Shannon
Wie in meiner Antwort angegeben: Es ist BEVORZUGT, es in Global.asax festzulegen, keine Anforderung. Sie können es sogar vor dem Aufruf des REST-Dienstes festlegen.
Sani Singh Huttunen
3
Unter diesem Link finden Sie eine mögliche Lösung.
Sani Singh Huttunen
173

Für alle, die diese Lösung auf Anfrage anwenden möchten, ist dies eine Option und verwendet einen Lambda-Ausdruck. Der gleiche Lambda-Ausdruck kann auch auf den von blak3r erwähnten globalen Filter angewendet werden. Diese Methode scheint .NET 4.5 zu erfordern.

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

In .NET 4.0 kann der Lambda-Ausdruck als solcher auf den globalen Filter angewendet werden

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
Adam Venezia
quelle
2
Gibt es eine Anforderungslösung für FtpWebRequest?
Timo
Es scheint gut in meinem 4.0
Nacht
Ich denke, es ist bei weitem eine schönere Lösung für die "globale" Variante, obwohl ich natürlich verstehen kann, warum Sie es wollen würden. Persönlich bevorzuge ich eine Anforderungsfactory, die dann diesen Validierungsrückruf verwaltet. Danke Adam, schöne Lösung.
Der Senator
2
Das Zurückgeben trueist etwas, das Sie tun können, wenn Sie während der Entwicklung experimentieren, es ist jedoch unsicher. Es sollte eine Bedingung sein.
Fred
1
Die Verwendung (HttpWebRequest)WebRequest.Create(url)ist vollkommen gültig, aber auf meiner Box ist sie HttpWebRequest.Create(url)noch in einem Projekt vorhanden, das auf .Net 4.6.2 abzielt. Die Wahl des Küchenchefs, aber zu diesem Zeitpunkt HttpClientist wahrscheinlich die bessere API zu verwenden.
Adam Venezia
53

Das hat bei mir funktioniert:

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
    };

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

blak3r
quelle
16
ServicePointManager.ServerCertificateValidationCallback + = (Absender, Zertifikat, Kette, sslPolicyErrors) => true;
David Rutgos
3
Immer true zurückzugeben ist unsicher. Es sollte bedingt true zurückgeben.
Fred
Dies ist pro Prozess und daher nicht sicher.
Mikhail Orlov
25

Es gibt auch die kurze Delegatenlösung:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 
Andrej Rommel
quelle
3
Immer zurückzukehren trueist unsicher.
Fred
7
Ja, es ist per Definition unsicher, immer allen SSL-Zertifikaten zu vertrauen. Vermeiden Sie dies nach Möglichkeit.
Andrej Rommel
@AndrejRommel was ist dein Weg empfohlen?
Kiquenet
2
Die empfohlene Methode besteht darin, ein gültiges SSL-Zertifikat zu erstellen und es ordnungsgemäß zu verwenden, wenn Sie die Kontrolle über den Server haben. Am Ende haben wir eine mit letsencrypt.org erstellt.
Andrej Rommel
5

Es wurde erwähnt, dass vor .NET 4.5 die Eigenschaft für die Anforderung des Zugriffs ServicePointManagernicht verfügbar war.

Hier ist der .NET 4.0-Code, mit dem Sie ServicePointpro Anfrage auf den zugreifen können . Sie erhalten keinen Zugriff auf den Rückruf pro Anforderung, sollten jedoch weitere Informationen zum Problem erhalten. Greifen Sie einfach auf die Eigenschaften zu scvPoint.Certificate(oder ClientCertificatewenn Sie dies bevorzugen).

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());
}
Jesse Chisholm
quelle
Einverstanden! Aber dann geht es in diesem OP darum, wie man ignoreihnen nicht vertraut.
Jesse Chisholm
Wie auch immer, ServicePointich kann nicht immer allen SSL-Zertifikaten vertrauen und auch nicht alle Zertifikate ignorieren , da ich nicht ServerCertificateValidationCallback in ServicePoint
Kiquenet
4

Nur im Übrigen ist dies die am wenigsten ausführliche Methode, um alle Zertifikatsüberprüfungen in einer bestimmten App zu deaktivieren, von denen ich weiß:

ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
Christian Findlay
quelle
4

Anstatt ServicePointManager einen Rückruf hinzuzufügen, der die Zertifikatsüberprüfung global überschreibt, können Sie den Rückruf für eine lokale Instanz von HttpClient festlegen. Dieser Ansatz sollte nur Aufrufe betreffen, die mit dieser Instanz von HttpClient getätigt wurden.

Hier ist ein Beispielcode, der zeigt, wie das Ignorieren von Zertifikatüberprüfungsfehlern für bestimmte Server in einem Web-API-Controller implementiert werden kann.

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;
    }

}
Sheldon
quelle
Funktioniert das nicht nur für .NET Core? (Oder wann immer ServerCertificateCustomValidationCallback zu HttpClientHandler hinzugefügt wurde)?
Phillyslick
Diese Lösung sollte in .Net Framework 4.5 und höher sowie in .Net Core funktionieren (obwohl ich sie nicht in .Net Core getestet habe).
Sheldon
@Sheldon, das war ein Juwel :) Wird in meinen Localhost-API-Aufrufen zwischen einer .net- und einer .net-Core-App mit Erfolg verwendet. Schöne Problemumgehung, ohne alle zu akzeptieren.
Groß
3

Basierend auf Adams Antwort und Robs Kommentar habe ich Folgendes verwendet:

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

was das "Ignorieren" etwas filtert. Natürlich können bei Bedarf weitere Emittenten hinzugefügt werden. Dies wurde in .NET 2.0 getestet, da wir älteren Code unterstützen müssen.

Andrej Grobler
quelle
@karank Entschuldigung für die verspätete Antwort - Sie kann überall vor dem eigentlichen Anruf hinzugefügt werden, z. vor dem Aufruf von request.GetResponse (). Beachten Sie, dass der Emittent in Ihrem Fall möglicherweise noch etwas anderes enthält.
Andrej Grobler
3

CA5386: Tools zur Analyse von Sicherheitslücken machen Sie auf diese Codes aufmerksam.

Richtiger Code:

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

Für .net Kern

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);
    }
}
Rich Hildebrand
quelle
2

Ausdrücklich ausgedrückt ...

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;
}
dev_O
quelle
0

Zusätzlich zu den Antworten von Sani und blak3r habe ich dem Startcode für meine Anwendung Folgendes hinzugefügt, jedoch in VB:

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

Scheint den Trick zu machen.

MCattle
quelle
0

Tipp: Mit dieser Methode können Sie auch Zertifikate verfolgen, die bald ablaufen. Dies kann Ihren Speck retten, wenn Sie ein Zertifikat entdecken, das bald abläuft, und es rechtzeitig reparieren lassen. Gut auch für Drittunternehmen - für uns ist dies DHL / FedEx. DHL hat gerade ein Zertifikat ablaufen lassen, das uns 3 Tage vor Thanksgiving vermasselt. Zum Glück bin ich da, um das Problem zu beheben ... diesmal!

    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;
            }
        }
    }
Simon_Weaver
quelle
Stellen Sie sicher, dass Sie mit der Situation umgehen, in der Ihr Warnmechanismus ein abgelaufenes Zertifikat haben kann - sonst kommt es zu einem Stapelüberlauf!
Simon_Weaver
Was ist ProwlUtil.StepReached?
Kiquenet
Entschuldigung, das ist nur meine eigene Methode, um die Prowl-API aufzurufen, die Benachrichtigungen an mein Telefon senden kann. Wie auch immer Sie sich anmelden möchten, es ist gut. Ich mag es, auf meinem Handy für solche Dinge abgehört zu werden!
Simon_Weaver
0

Mehrere Antworten oben funktionieren. Ich wollte einen Ansatz, bei dem ich nicht ständig Codeänderungen vornehmen musste und meinen Code nicht unsicher machte. Daher habe ich eine Whitelist erstellt. Die Whitelist kann in jedem Datenspeicher verwaltet werden. Ich habe die Konfigurationsdatei verwendet, da es sich um eine sehr kleine Liste handelt.

Mein Code ist unten.

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

Unity C # -Version dieser Lösung:

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;
}
Santiago Game Lover
quelle