SSL時の証明書チェックを無視する方法


132

私はHttpsリソースをリクエストするときに証明書チェックを無視する方法を探しています。これまでのところ、インターネットで役立つ記事を見つけました。

しかし、まだ問題があります。コードを確認してください。コードが何をしているのかわからないServicePointManager.ServerCertificateValidationCallback意味。

このデリゲートメソッドはいつ呼び出されますか?そしてもう1つの質問です。このコードをどこに記述すればよいですか。ServicePointManager.ServerCertificateValidationCallback実行前または前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;
    }
}   

回答:


67

唯一のグローバルがあるのでServicePointManager、設定ServicePointManager.ServerCertificateValidationCallbackは後続のすべての要求は、このポリシーを継承するという結果が得られます。これはグローバルな「設定」なのでGlobal.asaxのApplication_Startメソッドで設定することをお勧めます

コールバックを設定するとデフォルトの動作が上書きされ、自分でカスタム検証ルーチンを作成できます。


Global.asaxを持たないクライアントはどうですか?ローカルネットワークで実行されているRESTサービスをハンドヘルドデバイスから呼び出しています。
B.クレイシャノン

3
質問はに固有HttpWebRequestです。他の手段を使用している場合は、ドキュメントでこれを行う方法を調べる必要があります。
Sani Singh Huttunen 2014

私は次のようなHttpWebRequestにキャストされるWebRequestを使用しています:((HttpWebRequest)request).Accept = contentType;
B.クレイシャノン

私の回答で述べたように、Global.asaxで設定することが要件ではなく推奨されます。RESTサービスを呼び出す前に設定することもできます。
Sani Singh Huttunen

3
可能な解決策については、このリンクを参照してください。
Sani Singh Huttunen 2014

174

このソリューションをリクエストごとに適用することに関心のある人にとっては、これはオプションであり、ラムダ式を使用します。同じLambda式を、blak3rで言及されているグローバルフィルターにも適用できます。このメソッドは.NET 4.5を必要とするようです。

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

.NET 4.0では、ラムダ式をグローバルフィルターに適用できます。

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

2
FtpWebRequestの要求ごとのソリューションはありますか?
Timo

それは私の4.0で問題なく存在するようです
Nacht

「グローバル」バリアントの方がはるかに優れたソリューションだと思いますが、もちろん、なぜそれが必要なのかは理解できます。個人的には、この検証コールバックを管理するリクエストファクトリを支持しています。アダム、素晴らしい解決策をありがとう。
の上院議員

2
リターンtrueは、開発中に実験するときにできることですが、安全ではありません。条件付きでなければなりません。
フレッド

1
使用(HttpWebRequest)WebRequest.Create(url)は完全に有効ですが、私の箱では、HttpWebRequest.Create(url).Net 4.6.2を対象とするプロジェクトにまだ存在しています。Chefの選択ですが、現時点でHttpClientはおそらく、使用するAPIが優れています。
Adam Venezia

53

これは私のために働きました:

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

ここからの抜粋:http ://www.west-wind.com/weblog/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors


17
ServicePointManager.ServerCertificateValidationCallback + =(送信者、証明書、チェーン、sslPolicyErrors)=> true;
David Rutgos、2014

3
常にtrueを返すのは安全ではありません。条件付きでtrueを返す必要があります。
フレッド

これはプロセスごとなので、安全ではありません。
ミハイル・オルロフ2016年

25

また、短いデリゲートソリューションもあります。

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 

3
常に戻ることtrueは安全ではありません。
Fred

7
はい、常にすべてのSSL証明書を信頼することは、本質的に安全ではありません。可能であればそうすることは避けてください。
Andrej Rommel

@AndrejRommelあなたのやり方は何がお勧めですか?
Kiquenet 2018年

2
推奨される方法は、有効なSSL証明書を作成し、サーバーを制御できる場合はそれを適切に利用することです。最終的には、letsencrypt.orgを使用して作成しました。
Andrej Rommel

5

.NET 4.5以前は、プロパティへのアクセスを要求するプロパティが ServicePointManagerは利用できなかったと述べられています。

ServicePointリクエストごとににアクセスできる.NET 4.0コードを次に示します。リクエストごとのコールバックにはアクセスできませんが、問題の詳細を確認できるはずです。scvPoint.Certificate(または必要にClientCertificate応じて)プロパティにアクセスするだけです。

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

同意しました!しかし、このOPは、ignoreそれらを信頼するのではなく、それらをどのように扱うかについてです。
ジェシーチザム2018年

とにかく、ServicePointで委任していないため、ServicePointI 使用してすべてのSSL証明書を常に信頼できるわけではなく、すべての証明書を無視することもできないServerCertificateValidationCallback
Kiquenet

4

偶然にも、これは私が知っている特定のアプリですべての証明書検証をオフにする最も冗長な方法です。

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

4

証明書の検証をグローバルにオーバーライドするコールバックをServicePointManagerに追加する代わりに、HttpClientのローカルインスタンスにコールバックを設定できます。このアプローチは、HttpClientのインスタンスを使用して行われた呼び出しにのみ影響します。

以下は、特定のサーバーの証明書検証エラーを無視することをWeb APIコントローラーに実装する方法を示すサンプルコードです。

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

}

これは.NET Coreでのみ機能しませんか?(またはServerCertificateCustomValidationCallbackがHttpClientHandlerに追加されたときはいつでも)?
phillyslick

このソリューションは、.Net Framework 4.5以降および.Net Coreで動作するはずです(ただし、.Net Coreではテストしていません)。
シェルドン、

@Sheldon、これは宝石だった:) .netと.netコアアプリ間のlocalhost api-callsで使用され、成功しました。すべてを受け入れることなく、素晴らしい回避策。

3

アダムの答えとロブのコメントに基づいて、私はこれを使いました:

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

「無視」をある程度フィルタリングします。もちろん、必要に応じて他の発行者を追加できます。一部のレガシーコードをサポートする必要があるため、これは.NET 2.0でテストされました。


@karank返信が遅くなってすみません-実際の通話の前など、どこにでも追加できます。request.GetResponse()を呼び出す前。ただし、発行者にはあなたのケースに他のものが含まれている可能性があります。
Andrej Grobler 2014年

3

CA5386:脆弱性分析ツールがこれらのコードについて警告します。

正しいコード:

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

3

.netコアの場合

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

明示的に表現...

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とblak3rの回答に加えて、アプリケーションのスタートアップコードに次のコードを追加しましたが、VBです。

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

トリックを行うようです。


0

ヒント:この方法を使用して、まもなく期限切れになる証明書を追跡することもできます。これは、期限切れが近づいている証明書を発見し、時間内に修正できる場合、ベーコンを節約できます。サードパーティ企業にも適しています-私たちにとってこれはDHL / FedExです。DHLは、感謝祭の3日前に私たちを台無しにする証明書を失効させます。幸い、私はそれを修正しようとしています...今回は!

    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 2017年

なにProwlUtil.StepReached
Kiquenet 2018年

申し訳ありませんが、私の電話に通知を送信できるProwl APIを呼び出すための私の独自の方法です。記録したいけどいいです。私はこのようなことのために私の電話で盗聴されるのが好きです!
Simon_Weaver 2018年

0

上記のいくつかの答えが機能します。コードを変更し続ける必要がなく、コードが安全でなくなるようなアプローチが必要でした。したがって、ホワイトリストを作成しました。ホワイトリストはどのデータストアでも管理できます。非常に小さなリストなので、私は構成ファイルを使用しました。

私のコードは以下です。

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

0

このソリューションのUnity C#バージョン:

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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.