SSL을 사용할 때 인증서 확인을 무시하는 방법


132

Https 리소스를 요청할 때 인증서 검사를 무시하는 방법을 찾으려고 노력했지만 지금까지 인터넷에서 유용한 기사를 찾았습니다.

그러나 여전히 문제가 있습니다. 내 코드를 검토하십시오. 코드의 ServicePointManager.ServerCertificateValidationCallback의미를 이해하지 못합니다 .

이 델리게이트 메소드는 언제 호출됩니까? 그리고 한 번 더 질문하면이 코드를 어디에 작성해야합니까? 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.asaxApplication_Start 메소드에서 설정하는 것이 좋습니다.

콜백을 설정하면 기본 동작이 무시되고 사용자 정의 유효성 검사 루틴을 직접 만들 수 있습니다.


Global.asax가없는 클라이언트는 어떻습니까? 핸드 헬드 장치에서 로컬 네트워크에서 실행되는 REST 서비스를 호출하고 있습니다.
B. Clay Shannon

3
질문은에만 해당됩니다 HttpWebRequest. 다른 방법을 사용하는 경우이를 수행하는 방법을 설명서에서 확인해야합니다.
사니 싱 허트

HttpWebRequest로 캐스팅되는 WebRequest를 사용하고 있습니다. ((HttpWebRequest) request) .Accept = contentType;
B. Clay Shannon

내 대답에서 언급했듯이 Global.asax에서 요구 사항이 아닌 설정하는 것이 좋습니다. REST 서비스를 호출하기 전에 설정할 수도 있습니다.
Sani Singh Huttunen 2014

3
가능한 해결책 은 이 링크 를 참조하십시오 .
Sani Singh Huttunen 2014

174

요청별로이 솔루션을 적용하는 데 관심이있는 사람이라면이 옵션은 옵션이며 Lambda 표현식을 사용합니다. blak3r에서 언급 한 전역 필터에도 동일한 Lambda 식을 적용 할 수 있습니다. 이 방법에는 .NET 4.5가 필요한 것으로 보입니다.

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

.NET 4.0에서는 Lambda Expression을 전역 필터에 적용 할 수 있습니다.

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

2
FtpWebRequest에 대한 요청 당 솔루션이 있습니까?
Timo

내 4.0에 괜찮은 것 같습니다
Nacht

물론 '글로벌'변형에 대한 훨씬 더 나은 솔루션이라고 생각하지만 물론 원하는 이유를 이해할 수 있습니다. 개인적으로 요청 팩토리를 선호 하고이 유효성 검사 콜백을 관리합니다. 고마워 아담, 좋은 해결책.
상원 의원

2
반품 true은 개발 중에 실험 할 때 수행 할 수있는 작업이지만 안전하지 않습니다. 조건부 여야합니다.
Fred

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

3
항상 true를 반환하는 것은 안전하지 않습니다. 조건부로 true를 반환해야합니다.
Fred

이것은 프로세스 별이므로 안전하지 않습니다.
Mikhail Orlov

25

또한 짧은 대리자 솔루션이 있습니다.

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 

3
항상 돌아 오는 true것은 안전하지 않습니다.
Fred

7
예, 항상 모든 SSL 인증서를 신뢰하는 것은 정의상 안전하지 않습니다. 가능하면 그렇게하지 마십시오.
Andrej Rommel

@AndrejRommel 당신의 방법은 무엇을 권장합니까?
Kiquenet

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그들을 신뢰하지 않고 어떻게 해야하는지에 관한 것입니다.
Jesse Chisholm

어쨌든, 사용하지 ServicePoint내가 할 수 항상 신뢰 모든 SSL 인증서를 둘 다 모든 인증서를 무시 하지 않았기 때문에, ServerCertificateValidationCallback ServicePoint에 위임
Kiquenet

4

우연히도 이것은 내가 알고있는 주어진 응용 프로그램에서 모든 인증서 유효성 검사를 해제하는 가장 간단한 방법입니다.

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

4

인증서 유효성 검사를 전체적으로 재정의하는 ServicePointManager에 콜백을 추가하지 않고 HttpClient의 로컬 인스턴스에서 콜백을 설정할 수 있습니다. 이 방법은 해당 HttpClient 인스턴스를 사용하여 이루어진 호출에만 영향을 미칩니다.

다음은 특정 서버에 대한 인증서 유효성 검증 오류를 무시하는 방법이 웹 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 핵심 앱 간의 API 호출에 성공했습니다. 모두 수락하지 않고 좋은 해결 방법.

3

Adam의 답변과 Rob의 의견을 바탕으로 이것을 사용했습니다.

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

어느 정도 "무시"를 걸러냅니다. 필요에 따라 다른 발행자를 추가 할 수도 있습니다. 일부 레거시 코드를 지원해야하므로 .NET 2.0에서 테스트되었습니다.


@karank 답변이 늦어 죄송합니다-예를 들어 실제 통화 전에 어디든지 추가 할 수 있습니다. request.GetResponse ()를 호출하기 전에 그러나 발급자에게는 귀하의 경우에 다른 것이 포함될 수 있습니다.
Andrej Grobler 1

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

무엇입니까 ProwlUtil.StepReached?
Kiquenet

전화로 알림을 보낼 수있는 Prowl API를 호출하는 방법은 저의 죄송합니다. 그러나 당신은 그것을 기록하고 싶습니다. 나는 이런 것들에 대해 휴대 전화에 버그를 갖고 싶어합니다!
Simon_Weaver

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.