HTTPS y SSL3_GET_SERVER_CERTIFICATE: error de verificación del certificado, CA está bien

208

Estoy usando XAMPP para el desarrollo. Recientemente actualicé mi instalación de xampp de una versión anterior a 1.7.3.

Ahora, cuando rizo los sitios habilitados para HTTPS, obtengo la siguiente excepción

Error grave: excepción no detectada 'RequestCore_Exception' con el mensaje 'recurso cURL: ID de recurso # 55; Error de cURL: problema con el certificado SSL, verifique que el certificado de CA esté bien. Detalles: error: 14090086: rutinas SSL: SSL3_GET_SERVER_CERTIFICATE: verificación de certificado fallida (60) '

Todos sugieren usar algunas opciones de rizo específicas del código PHP para solucionar este problema. Creo que este no debería ser el camino. Porque no tuve ningún problema con mi versión anterior de XAMPP y sucedió solo después de instalar la nueva versión.

Necesito ayuda para determinar qué cambios de configuración en mi instalación de PHP, Apache, etc. pueden solucionar este problema.

Josnidhin
fuente

Respuestas:

145

curl solía incluir una lista de CA aceptadas, pero ya no incluye CUALQUIER certificado de CA. Entonces, por defecto, rechazará todos los certificados SSL como no verificables.

Tendrás que obtener el certificado de tu CA y apuntarlo. Más detalles en Detalles de cURLS sobre certificados SSL de servidor .

Marc B
fuente
44
El rizo está sucediendo en la biblioteca php de servicios web de Amazon. No entendí cómo solucionarlo sin editar el código de la biblioteca.
Josnidhin
41
Luego apague la verificación del certificado ( CURLOPT_SSL_VERIFYPEER-> falso). Puede agregar el certificado de CA del sitio con el que está tratando de hacer SSL o deshabilitar la verificación de CA. Esas son las dos únicas opciones disponibles.
Marc B
78
Para su información - la creación CURLOPT_SSL_VERIFYPEERde falsederrotas el propósito de utilizar SSL.
Hasta
13
@ ¿Hasta no vence la mitad del propósito de SSL? Todavía tiene privacidad entre usted y su compañero: simplemente no tiene la autenticidad de su compañero.
Mark Fox
10
sin autenticidad, ¿qué sentido tiene cifrar los datos que envía? Si ha sido MITMed, entonces los datos están comprometidos de todos modos
hdgarrood
290

Es un problema bastante común en Windows. Es necesario sólo para conjunto cacert.pemdecurl.cainfo .

Desde PHP 5.3.7 podrías hacer:

  1. descarga https://curl.haxx.se/ca/cacert.pem y guárdelo en algún lugar.
  2. actualización php.ini: agregue curl.cainfo = "PATH_TO / cacert.pem"

De lo contrario, deberá hacer lo siguiente para cada recurso cURL:

curl_setopt ($ch, CURLOPT_CAINFO, "PATH_TO/cacert.pem");
Артур Курицын
fuente
2
Esto funcionó para mí en XAMPP en OS X. Solucionó un problema por el cual un complemento de Wordpress no se actualizaba por no poder ubicar un certificado local.
Jonathan Nicol
8
Para cualquier otra persona que intente resolver este problema en Windows usando Apache, tuve que configurar la ruta completa (es decir, C: \ PATH_TO \ cacert.pem) en mi código PHP. En IIS, la ruta relativa parecía funcionar bien.
http203
Si cacert.pem está en el mismo directorio, curl_setopt ($ ch, CURLOPT_CAINFO, dirname ( FILE ). '/Cacert.pem'); funcionará
mujaffars
77
Cuando use WampServer con 2., debe agregar la variable a dos php.iniarchivos separados . Ver stackoverflow.com/a/25706713/1101095
Nate
Lo desconcertante / irónico es que puede descargar curl.haxx.se/ca/cacert.pem a través de HTTPS sin especificar ninguna opción adicional. ¿El certificado de curl.haxx.se está respaldado en curl?
qbolec
84

Advertencia: esto puede presentar problemas de seguridad contra los cuales SSL está diseñado para proteger, lo que hace que toda su base de código sea insegura. Va en contra de todas las prácticas recomendadas.

Pero una solución realmente simple que funcionó para mí fue llamar:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

antes de llamar:

curl_exec():

en el archivo php

Creo que esto deshabilita toda verificación de certificados SSL.

Chris Dutrow
fuente
65
... y al deshabilitar la verificación de los certificados, deja la puerta abierta a posibles ataques MITM, de los cuales SSL / TLS de lo contrario pretende proteger. ¡NO HAGAS ESTO!
Bruno
12
Sip. Debería haber llamado más la atención sobre esto en la respuesta. Solo haga esto si no está trabajando en algo importante. Lo uso en localhost para acceder a sitios web que programé personalmente.
Chris Dutrow
3
Voto negativo de mi parte. Esta es una solución sucia para que su código funcione, pero no es una solución. La respuesta proporcionada por Артур Курицын es mucho mejor.
Ilija
2
@Bruno Esta es la solución perfecta, para scripts de ayuda, pruebas, aplicaciones confiables, intranet, ..... Todos los que conocen UN POCO sobre SSL, saben en qué casos se puede omitir la validación del certificado. ¡¡Así que todos los comentarios 'inteligentes' sobre esta respuesta y cosas como 'NO HAGAS ESTO' no tienen sentido !!
Kenyakorn Ketsombut
55
... " Todos los que conocen UN POCO sobre SSL [...] " ... y se sorprenderán de cuántas personas ni siquiera se molestan en conocer un poco sobre los conceptos básicos de SSL / TLS, y están llegando aquí para copiar / pegar una solución rápida para su mensaje de error.
Bruno
53

Fuente: http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html

Curl: problema con el certificado SSL, verifique que el certificado CA esté bien

07 de abril de 2006

Al abrir una url segura con Curl, puede obtener el siguiente error:

Problema con el certificado SSL, verifique que el certificado CA esté bien

Explicaré por qué el error y qué debes hacer al respecto.

La forma más fácil de deshacerse del error sería agregar las siguientes dos líneas a su secuencia de comandos. Esta solución plantea un riesgo de seguridad aunque.

//WARNING: this would prevent curl from detecting a 'man in the middle' attack
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0); 

Veamos qué hacen estos dos parámetros. Citando el manual.

CURLOPT_SSL_VERIFYHOST : 1 para verificar la existencia de un nombre común en el certificado de igual SSL. 2 para verificar la existencia de un nombre común y también verificar que coincida con el nombre de host proporcionado.

CURLOPT_SSL_VERIFYPEER : FALSE para evitar que CURL verifique el certificado del par. Los certificados alternativos para verificar se pueden especificar con la opción CURLOPT_CAINFO o se puede especificar un directorio de certificados con la opción CURLOPT_CAPATH. CURLOPT_SSL_VERIFYHOST también puede necesitar ser VERDADERO o FALSO si CURLOPT_SSL_VERIFYPEER está deshabilitado (el valor predeterminado es 2). Establecer CURLOPT_SSL_VERIFYHOST en 2 (este es el valor predeterminado) garantizará que el certificado que se le presente tenga un 'nombre común' que coincida con la URN que está utilizando para acceder al recurso remoto. Este es un chequeo saludable pero no garantiza que su programa no esté siendo engañado.

Introduzca el 'hombre en el medio'

En su lugar, se podría confundir su programa para hablar con otro servidor. Esto se puede lograr a través de varios mecanismos, como dns o envenenamiento por arpa (esta es una historia para otro día). El intruso también puede auto-firmar un certificado con el mismo "nombre común" que su programa espera. La comunicación aún estaría encriptada, pero estarías revelando tus secretos a un impostor. Este tipo de ataque se llama 'hombre en el medio'

Derrotar al 'hombre en el medio'

Bueno, necesitamos verificar que el certificado que se nos presenta es bueno de verdad. Hacemos esto comparándolo con un certificado en el que confiamos * de manera razonable.

Si el recurso remoto está protegido por un certificado emitido por una de las principales entidades emisoras de certificados como Verisign, GeoTrust et al, puede comparar con seguridad con el paquete de certificados de CA de Mozilla que puede obtener de http://curl.haxx.se/docs/caextract .html

Guarde el archivo cacert.pemen algún lugar de su servidor y configure las siguientes opciones en su secuencia de comandos.

curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, TRUE); 
curl_setopt ($ch, CURLOPT_CAINFO, "pathto/cacert.pem");

para todo el crédito de información anterior va a: http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html

Deepak Oberoi
fuente
38
En general, se considera de buena educación acreditar la fuente de su información y solo citar ciertas partes relevantes para la pregunta, en lugar de simplemente copiarla y pegarla aquí.
Dan Herd
1
Lo siento, he estado fuera, sí, le pido a Dan por eso y actualizo The Post
Deepak Oberoi
66
Al menos Deepak hizo el esfuerzo de investigarlo. @danherd Danherd, ¿acabas de hacer la investigación para descubrir que tomó el código de alguna parte? ¿Cuál fue el derecho de atribución de este código? En lugar de perder el tiempo para encontrar los errores de otra persona, intente ayudar a alguien por su cuenta. ¡No pelees, comparte!
GTodorov
17

Las soluciones anteriores son geniales, pero si está utilizando WampServer, es posible que la configuración de la curl.cainfovariable php.inino funcione.

Finalmente encontré que WampServer tiene dos php.iniarchivos:

C:\wamp\bin\apache\Apachex.x.x\bin
C:\wamp\bin\php\phpx.x.xx

Aparentemente, el primero se usa para cuando se invocan archivos PHP a través de un navegador web, mientras que el segundo se usa cuando se invoca un comando a través de la línea de comando o shell_exec().

TL; DR

Si usa WampServer, debe agregar la curl.cainfolínea a ambos php.ini archivos.

Nate
fuente
6

Por el amor de todo lo que es santo ...

En mi caso, tuve que establecer la openssl.cafilevariable de configuración de PHP en la ruta del archivo PEM.

Confío en que es muy cierto que hay muchos sistemas en los que establecer curl.cainfola configuración de PHP es exactamente lo que se necesita, pero en el entorno con el que estoy trabajando, que es el contenedor acoplador eboraas / laravel , que usa Debian 8 (jessie) y PHP 5.6, establecer esa variable no funcionó.

Noté que la salida de php -ino mencionaba nada sobre esa configuración de configuración en particular, pero tenía algunas líneas al respecto openssl. Hay una opción openssl.capathy una openssl.cafile, pero solo configurar el segundo permite el rizo a través de PHP para finalmente estar bien con las URL HTTPS.

Spencer Williams
fuente
¡Gracias! La configuración de curl.cainfo tampoco funcionó para mí, pero la configuración de openssl.cafile sí. Estoy en Windows 7 con XAMPP y PHP 7.1.1.
knezmilos
@knezmilos ¿cómo hiciste para configurar el archivo openssl.cafile? ¿Dónde lo descargaste y cómo lo activaste?
Krys
Bueno, ha pasado un tiempo, pero creo que es algo como esto: curl.cainfo = "C: \ xampp \ cacert \ cacert.pem" y openssl.cafile = "C: \ xampp \ cacert \ cacert.pem" en php. ini, aunque creo que obtuve el archivo pem de una de las respuestas aquí.
knezmilos
1
"Por el amor de todo lo que es santo ..." de hecho. Esto funcionó para mi configuración de Ubuntu 18.08 / Apache / Php7.2. Si el error de curl apunta al archivo correcto, entonces es sin duda culpa de OpenSls
JTG
4

A veces, si la aplicación que intenta contactar tiene certificados autofirmados, el cacert.pem normal de http://curl.haxx.se/ca/cacert.pem no resuelve el problema.

Si está seguro acerca de la URL del punto final del servicio, hágalo a través del navegador, guarde el certificado manualmente en el formato "Certificado X 509 con cadena (PEM)". Apunte este archivo de certificado con el

curl_setopt ($ch, CURLOPT_CAINFO, "pathto/{downloaded certificate chain file}");   
madRai
fuente
4

Tengo el mismo error en Amazon AMI Linux.

He resuelto por el ajuste curl.cainfo en /etc/php.d/curl.ini

https://gist.github.com/reinaldomendes/97fb2ce8a606ec813c4b

Adición octubre 2018

En Amazon Linux v1 edite este archivo

vi /etc/php.d/20-curl.ini

Para agregar esta línea

curl.cainfo="/etc/ssl/certs/ca-bundle.crt"
Reinaldo Mendes
fuente
¡Perfecto gracias! Actualicé la pregunta para agregar exactamente lo que hice que resolvió el problema para mí, en lugar de crear otra respuesta.
Tim
3

Al configurar las opciones de curvatura para CURLOPT_CAINFO, recuerde usar comillas simples, usar comillas dobles solo causará otro error. Entonces su opción debería verse así:

curl_setopt ($ch, CURLOPT_CAINFO, 'c:\wamp\www\mywebfolder\cacert.pem');

Además, en su configuración de archivo php.ini debe escribirse como: (observe mis comillas dobles)

curl.cainfo = "C:\wamp\www\mywebfolder"

Lo puse directamente debajo de la línea que dice esto: extension=php_curl.dll

(Solo para fines de organización, puede colocarlo en cualquier lugar dentro de su php.ini, solo lo coloco cerca de otra referencia de rizo, así que cuando busco usando la palabra clave curl puedo encontrar ambas referencias de rizo en un área).

LOwens1931
fuente
1
Espero que php.ini apunte al archivo pem en lugar de a su carpeta principal
dejjub-AIS
2

Terminé aquí cuando intentaba obtener GuzzleHttp (php + apache en Mac) para obtener una página de www.googleapis.com.

Aquí estaba mi solución final en caso de que ayude a alguien.

Mire la cadena de certificados para cualquier dominio que le esté dando este error. Para mí fue googleapis.com

openssl s_client -host www.googleapis.com -port 443

Volverás algo como esto:

Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.googleapis.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority

Nota: Capturé esto después de solucionar el problema, ya que la salida de su cadena puede verse diferente.

Entonces debes mirar los certificados permitidos en php. Ejecute phpinfo () en una página.

<?php echo phpinfo();

Luego busque el archivo de certificado que se carga desde la salida de la página:

openssl.cafile  /usr/local/php5/ssl/certs/cacert.pem

Este es el archivo que necesitará corregir agregando los certificados correctos.

sudo nano /usr/local/php5/ssl/certs/cacert.pem

Básicamente, debe agregar las "firmas" de certificados correctas al final de este archivo.

Puede encontrar algunos de ellos aquí: es posible que necesite buscar / buscar en Google otros en la cadena si los necesita.

Se ven así:

imagen de certificado de ejemplo

( Nota: esta es una imagen para que la gente no simplemente copie / pegue certificados de stackoverflow )

Una vez que los certificados correctos estén en este archivo, reinicie apache y pruebe.

TrophyGeek
fuente
0

Puede intentar reinstalar el ca-certificatespaquete o permitir explícitamente el certificado en cuestión como se describe aquí .

sitio
fuente
-5

¡La solución es muy simple! Pon esta línea antes curl_exec:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Para mi funciona.

Zsolt Boszormenyi
fuente
77
Nunca, nunca desactive la verificación por pares a menos que no le importe si los datos se ven comprometidos en tránsito.
rdlowrey
Convenido. Si desea una aplicación segura, necesita verificación por pares.
braden
2
"Nunca, nunca deshabilite la verificación por pares" A MENOS que desee la funcionalidad predeterminada del navegador jaja. Además, ¿por qué es tanto rechazado? Esta es la única respuesta que es corta, dulce, al punto y efectiva.
Adam F
@AdamF FYI, los navegadores sí verifican el certificado par de manera predeterminada, solo le dan la opción de omitir los errores manualmente, con una advertencia.
Bruno