C # ¿Ignorar errores de certificado?

159

Recibo el siguiente error durante una solicitud de servicio web a un servicio web remoto:

No se pudo establecer una relación de confianza para el canal seguro SSL / TLS. ---> System.Security.Authentication.AuthenticationException: el certificado remoto no es válido de acuerdo con el procedimiento de validación.

¿Hay alguna forma de ignorar este error y continuar?

Parece que el certificado remoto no está firmado.

El sitio al que me conecto es www.czebox.cz, así que siéntase libre de visitar el sitio y observe que incluso los navegadores arrojan excepciones de seguridad.

JL
fuente

Respuestas:

341

Agregue un controlador de validación de certificado. La devolución truepermitirá ignorar el error de validación:

ServicePointManager
    .ServerCertificateValidationCallback += 
    (sender, cert, chain, sslPolicyErrors) => true;
Peter Lillevold
fuente
66
Esto es aún más útil de lo que parece a primera vista. Me encontré con el problema del OP mientras usaba los Servicios web intercambiados gestionados (EWS). Pensé que no podía usar esta respuesta ya que no tenía acceso a las llamadas SOAP de bajo nivel que estaba haciendo esa biblioteca administrada. Pero cuando le eché otro vistazo, me di cuenta de que ServicePointManager se destaca por sí solo. Entonces, agregué la devolución de llamada anterior antes de inicializar ExchangeService y funcionó de maravilla.
Mark Meuer
2
Aquí hay un ejemplo de cómo aplicar el bypass globalmente. Para todos nosotros en malas prácticas. (A veces no tienes otra opción) jasig.275507.n4.nabble.com/…
snowYetis
1
Muchas gracias, esto resuelve el problema temporalmente. Agregue este código en Startup.cs en Web Api
Sivalingaamorthy
2
@ MarkMeuer casi iba a renunciar a esta solución para mi problema de API EWS, pero luego vi su comentario.
Mahen
77
@MiguelVeloso eres libre de votar por supuesto, pero ten en cuenta que ni la pregunta ni la respuesta discuten el lado de seguridad de esto. El tema es explícitamente "cómo ignorar el error de validación", no "por qué deberíamos hacer / no hacer esto", que es un tema completamente diferente. Entrar en una discusión sobre por qué el OP no debería hacerlo solo enturbiaría las aguas, ya que los comentaristas han señalado que hay casos razonables en los que realmente haría esto. Así que nos atenemos al tema y resolvemos el problema.
Peter Lillevold
40

Permitir todos los certificados es muy poderoso, pero también podría ser peligroso. Si desea permitir solo certificados válidos más algunos certificados determinados, podría hacerlo de esta manera.

Núcleo .Net:

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

Actualizar:

Cómo obtener cert.GetCertHashString()valor en Chrome:

Haga clic en Secureo Not Secureen la barra de direcciones.

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Luego haga clic en Certificado -> Detalles -> Huella digital y copie el valor. Recuerda hacer cert.GetCertHashString().ToLower().

ingrese la descripción de la imagen aquí

Ogglas
fuente
3
@MiguelVeloso Completamente de acuerdo. Esto permite omitir la comprobación (con suerte) de uno o dos certificados sin comprometer la seguridad por completo.
Kemuel Sanchez
¿Cómo puedo obtener Hash Stringun certificado?
Kiquenet
De cualquier @Kiquenet depurar el código y ejecutar cert.GetCertHashString()desde Immediate windowo cheque certificado Thumbprinten su navegador o MMCsi está instalado localmente.
Ogglas
El servidor está bajo nuestro control, ¿sigue siendo seguro usar el código de @ Ogglas en la producción? Usando TLS / SSL, ¿se puede detener un ataque como man-in-the-middle?
Pingpong
Muchas gracias, gran ayuda.
Wowo Ot
30

Método 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;
} 
Amén Ra
fuente
2
Tuve que agregar una línea más para que esto funcione con mi código (estoy usando websocket4net). System.Net.ServicePointManager.CheckCertificateRevocationList = false; Inmediatamente después de configurar la devolución de llamada de validación del certificado del servidor.
kalyanswaroop
24

La razón por la que está fallando no es porque no está firmado, sino porque el cliente no confía en el certificado raíz. En lugar de desactivar la validación SSL, un enfoque alternativo sería agregar el certificado de CA raíz a la lista de CA en las que confía su aplicación.

Este es el certificado raíz de CA en el que su aplicación actualmente no confía:

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

Puede decodificar y ver este certificado utilizando

este decodificador de certificados u otro decodificador de certificados

bignum
fuente
¡Si! Este es mi caso, pero ¿cómo puedo agregar el certificado en Azure, sin una máquina virtual? ¿Puedo usar la API X509Store? Voy a intentar eso mañana, pero cualquier información es bienvenida aquí
João Antunes
7

Para deshabilitar la validación del certificado SSL en la configuración del cliente.

<behaviors>
   <endpointBehaviors>
      <behavior name="DisableSSLCertificateValidation">
         <clientCredentials>
             <serviceCertificate>
                <sslCertificateAuthentication certificateValidationMode="None" />
              </serviceCertificate>
           </clientCredentials>
        </behavior>
d.marzo
fuente
¿Es esto web.config ? ¿Alguna alternativa para ASP.NET Core?
Shimmy Weitzhandler
5

Este código me funcionó. Tuve que agregar TLS2 porque esa era la URL que me interesaba.

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);
}
usuario2347528
fuente
3

Omitir certificado 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
fuente
2

Si está utilizando sockets directamente y se está autenticando como cliente, entonces el método de devolución de llamada de Service Point Manager no funcionará. Esto es lo que funcionó para mí. Úselo únicamente para fines de prueba .

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

La clave aquí es proporcionar la devolución de llamada de validación de certificado remota directamente en el constructor de la secuencia SSL.

Mario
fuente
1

Para ampliar aún más la publicación de BIGNUM: idealmente, desea una solución que simule las condiciones que verá en la producción y modificar su código no lo hará y podría ser peligroso si olvida sacar el código antes de implementarlo.

Necesitará un certificado autofirmado de algún tipo. Si sabe lo que está haciendo, puede usar el BIGNUM binario publicado, pero si no puede ir a buscar el certificado. Si está utilizando IIS Express, ya tendrá uno de estos, solo tendrá que encontrarlo. Abra Firefox o el navegador que desee y vaya a su sitio web de desarrollo. Debería poder ver la información del certificado desde la barra de URL y, dependiendo de su navegador, debería poder exportar el certificado a un archivo.

A continuación, abra MMC.exe y agregue el complemento Certificado. Importe su archivo de certificado en la tienda Trusted Root Certificate Authorities y eso es todo lo que necesita. Es importante asegurarse de que entre en esa tienda y no en otra tienda como 'Personal'. Si no está familiarizado con MMC o certificados, existen numerosos sitios web con información sobre cómo hacerlo.

Ahora, su computadora en su conjunto confiará implícitamente en cualquier certificado que haya generado y no necesitará agregar código para manejar esto especialmente. Cuando pase a producción, continuará funcionando siempre que tenga un certificado válido adecuado instalado allí. No haga esto en un servidor de producción; eso sería malo y no funcionará para ningún otro cliente que no sea el servidor en sí.

Nigel Thomas
fuente
1

Esto funciona para .Net Core. Llame a su cliente de jabón:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
                new X509ServiceCertificateAuthentication()
                {
                    CertificateValidationMode = X509CertificateValidationMode.None,
                    RevocationMode = X509RevocationMode.NoCheck
                };  
Rimi
fuente