HTTPS et SSL3_GET_SERVER_CERTIFICATE: la vérification du certificat a échoué, l'autorité de certification est OK


208

j'utilise XAMPP pour le développement. Récemment, j'ai mis à niveau mon installation de xampp d'une ancienne version vers 1.7.3.

Maintenant, lorsque je recourbe les sites compatibles HTTPS, j'obtiens l'exception suivante

Erreur fatale: exception non interceptée 'RequestCore_Exception' avec le message 'ressource cURL: ID de ressource # 55; Erreur cURL: problème de certificat SSL, vérifiez que le certificat CA est OK. Détails: erreur: 14090086: routines SSL: SSL3_GET_SERVER_CERTIFICATE: échec de la vérification du certificat (60) '

Tout le monde suggère d'utiliser certaines options de curl spécifiques du code PHP pour résoudre ce problème. Je pense que cela ne devrait pas être le cas. Parce que je n'ai eu aucun problème avec mon ancienne version de XAMPP et ce n'est arrivé qu'après l'installation de la nouvelle version.

J'ai besoin d'aide pour comprendre quels paramètres changent dans mon installation PHP, Apache, etc. peut résoudre ce problème.

Réponses:


145

curl incluait auparavant une liste des autorités de certification acceptées, mais ne regroupe plus aucun certificat d'autorité de certification. Ainsi, par défaut, il rejettera tous les certificats SSL comme invérifiables.

Vous devrez obtenir le certificat de votre autorité de certification et pointer vers lui. Plus de détails sur Détails de cURLS sur les certificats SSL du serveur .


4
La boucle se produit dans la bibliothèque php d'Amazon Web Services. Je n'ai pas compris comment le corriger sans modifier le code de la bibliothèque.
Josnidhin

41
Désactivez ensuite la vérification du certificat ( CURLOPT_SSL_VERIFYPEER-> false). Vous pouvez soit ajouter le certificat CA du site avec lequel vous essayez de faire du SSL, soit désactiver la vérification CA. Ce sont les deux seules options disponibles.
Marc B

78
Juste fyi - réglage CURLOPT_SSL_VERIFYPEERpour falsevaincre le but de l'utilisation de SSL.
Jusqu'au

13
@Till n'atteint-il pas la moitié de l'objectif de SSL? Vous bénéficiez toujours d'une intimité entre vous et votre homologue: vous n'avez tout simplement pas l'authenticité de votre homologue.
Mark Fox

10
sans authenticité, quel est l'intérêt de crypter les données que vous envoyez? Si vous avez été MITMed, les données sont quand même compromises
hdgarrood

290

C'est un problème assez courant dans Windows. Il vous suffit de vous mettre cacert.pemà curl.cainfo.

Depuis PHP 5.3.7, vous pouvez faire:

  1. téléchargez https://curl.haxx.se/ca/cacert.pem et enregistrez-le quelque part.
  2. mise à jour php.ini- ajoutez curl.cainfo = "PATH_TO / cacert.pem"

Sinon, vous devrez effectuer les opérations suivantes pour chaque ressource cURL:

curl_setopt ($ch, CURLOPT_CAINFO, "PATH_TO/cacert.pem");

2
Cela a fonctionné pour moi dans XAMPP sur OS X. Il a résolu un problème où un plugin Wordpress ne se mettait pas à jour en raison de l'impossibilité de localiser un certificat local.
Jonathan Nicol

8
Pour toute autre personne essayant de résoudre ce problème sur Windows en utilisant Apache, j'ai dû définir le chemin complet (c'est-à-dire C: \ PATH_TO \ cacert.pem) dans mon code PHP. Sur IIS, le chemin relatif semblait fonctionner correctement.
http203

Si le cacert.pem est dans le même répertoire, alors curl_setopt ($ ch, CURLOPT_CAINFO, dirname ( FILE ). '/Cacert.pem'); fonctionnera
mujaffars

7
Lorsque vous utilisez WampServer avec 2., vous devez ajouter la variable à deux php.inifichiers distincts . Voir stackoverflow.com/a/25706713/1101095
Nate

Ce qui est déroutant / ironique, c'est que vous pouvez télécharger curl.haxx.se/ca/cacert.pem via HTTPS sans spécifier d'options supplémentaires. Le certificat pour curl.haxx.se est-il sauvegardé dans curl lui-même?
qbolec

84

Avertissement: cela peut introduire des problèmes de sécurité contre lesquels SSL est conçu, ce qui rend l'ensemble de votre base de code non sécurisé. Cela va à l'encontre de toutes les pratiques recommandées.

Mais une solution vraiment simple qui a fonctionné pour moi était d'appeler:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

avant d'appeler:

curl_exec():

dans le fichier php.

Je crois que cela désactive toute vérification des certificats SSL.


65
... et en désactivant la vérification des certificats, vous laissez la porte ouverte à d'éventuelles attaques MITM contre lesquelles SSL / TLS vise autrement à se protéger. NE FAITES PAS CELA!
Bruno

12
Ouaip. J'aurais dû attirer davantage l'attention sur ce point dans la réponse. Ne faites cela que si vous ne travaillez sur rien d'important. Je l'utilise sur localhost pour accéder à des sites Web que j'ai personnellement programmés.
Chris Dutrow

3
Downvote de moi. C'est un correctif pour faire fonctionner votre code, mais pas une solution. La réponse fournie par Артур Курицын est bien meilleure.
Ilija

2
@Bruno C'est la solution parfaite, pour les scripts d'aide, les tests, les applications de confiance, l'intranet, ... Tout le monde qui connaît UN PEU de SSL, sait dans quels cas la validation du certificat peut être ignorée. Donc, tous les commentaires «intelligents» sur cette réponse et des choses comme «NE FAITES PAS CELA» sont juste des absurdités !!
Kenyakorn Ketsombut

5
... " Tous ceux qui connaissent UN PEU de SSL [...] " ... et vous seriez surpris de voir combien de personnes ne prennent même pas la peine de connaître un peu les bases de SSL / TLS, et viennent ici pour copier / coller un correctif rapide pour leur message d'erreur.
Bruno

53

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

Curl: problème de certificat SSL, vérifiez que le certificat CA est OK

07 avril 2006

Lorsque vous ouvrez une URL sécurisée avec Curl, vous pouvez obtenir l'erreur suivante:

Problème de certificat SSL, vérifiez que le certificat CA est OK

Je vais vous expliquer pourquoi l'erreur et ce que vous devez faire à ce sujet.

Le moyen le plus simple de se débarrasser de l'erreur serait d'ajouter les deux lignes suivantes à votre script. Cette solution pose un risque pour la sécurité.

//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); 

Voyons ce que font ces deux paramètres. Citant le manuel.

CURLOPT_SSL_VERIFYHOST : 1 pour vérifier l'existence d'un nom commun dans le certificat d'homologue SSL. 2 pour vérifier l'existence d'un nom commun et vérifier également qu'il correspond au nom d'hôte fourni.

CURLOPT_SSL_VERIFYPEER : FALSE pour empêcher CURL de vérifier le certificat de l'homologue. D'autres certificats à vérifier peuvent être spécifiés avec l'option CURLOPT_CAINFO ou un répertoire de certificats peut être spécifié avec l'option CURLOPT_CAPATH. CURLOPT_SSL_VERIFYHOST peut également avoir besoin d'être VRAI ou FAUX si CURLOPT_SSL_VERIFYPEER est désactivé (il est par défaut 2). La définition de CURLOPT_SSL_VERIFYHOST sur 2 (il s'agit de la valeur par défaut) garantira que le certificat qui vous est présenté a un «nom commun» correspondant à l'URN que vous utilisez pour accéder à la ressource distante. Il s'agit d'une vérification saine, mais cela ne garantit pas que votre programme n'est pas trompé.

Entrez l'homme au milieu

Votre programme pourrait être induit en erreur en parlant à un autre serveur à la place. Cela peut être réalisé grâce à plusieurs mécanismes, comme le DNS ou l'empoisonnement par arp (c'est une histoire pour un autre jour). L'intrus peut également auto-signer un certificat avec le même «nom commun» que votre programme attend. La communication serait toujours cryptée mais vous confieriez vos secrets à un imposteur. Ce type d'attaque est appelé «l'homme au milieu»

Vaincre «l'homme au milieu»

Eh bien, nous devons vérifier que le certificat qui nous est présenté est bien réel. Nous le faisons en le comparant à un certificat auquel nous faisons confiance *.

Si la ressource distante est protégée par un certificat émis par l'une des principales autorités de certification comme Verisign, GeoTrust et al, vous pouvez comparer en toute sécurité le paquet de certificats de l'autorité de certification de Mozilla que vous pouvez obtenir sur http://curl.haxx.se/docs/caextract .html

Enregistrez le fichier cacert.pemquelque part sur votre serveur et définissez les options suivantes dans votre script.

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

pour tous les crédits d'informations ci-dessus: http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html


38
Il est généralement considéré comme poli de créditer la source de vos informations et de ne citer que certaines parties pertinentes à la question, plutôt que de simplement les copier et les coller ici!
Dan Herd

1
Désolé, j'ai été absent, oui, j'applique Dan pour cela et j'ai mis à jour The Post
Deepak Oberoi

6
Au moins, Deepak a fait l'effort de le rechercher. @danherd Alors danherd, vous venez de faire des recherches pour découvrir qu'il a pris le code quelque part? Quel était le droit d'attribution de ce code? Au lieu de perdre votre temps à trouver les erreurs de quelqu'un d'autre, essayez d'aider quelqu'un par vous-même. Ne vous battez pas, partagez!
GTodorov

17

Les solutions ci-dessus sont excellentes, mais si vous utilisez WampServer, vous trouverez peut-être que la définition de la curl.cainfovariable dans php.inine fonctionne pas.

J'ai finalement trouvé que WampServer avait deux php.inifichiers:

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

Le premier est apparemment utilisé lorsque les fichiers PHP sont invoqués via un navigateur Web, tandis que le second est utilisé lorsqu'une commande est invoquée via la ligne de commande ou shell_exec().

TL; DR

Si vous utilisez WampServer, vous devez ajouter le curl.cainfo ligne aux deux php.ini fichiers.


6

Pour l'amour de tout ce qui est saint ...

Dans mon cas, j'ai dû régler la openssl.cafile variable de configuration PHP sur le chemin du fichier PEM.

J'espère qu'il est très vrai qu'il existe de nombreux systèmes où la configuration curl.cainfodans la configuration de PHP est exactement ce qui est nécessaire, mais dans l'environnement avec lequel je travaille, qui est le eboraas / laravel conteneur docker , qui utilise Debian 8 (jessie) et PHP 5.6, définir cette variable n'a pas fait l'affaire.

J'ai remarqué que la sortie de php -ine mentionnait rien sur ce paramètre de configuration particulier, mais elle contenait quelques lignes openssl. Il y a à la fois une option openssl.capathet une openssl.cafileoption, mais le simple fait de définir la deuxième boucle autorisée via PHP pour enfin être compatible avec les URL HTTPS.


Je vous remercie! Définir le curl.cainfo n'a pas fonctionné pour moi non plus, mais le paramètre openssl.cafile l'a fait! Je suis sur Windows 7 avec XAMPP et PHP 7.1.1.
knezmilos

@knezmilos comment avez-vous procédé pour configurer le openssl.cafile? où avez-vous téléchargé et comment l'activez-vous?
Krys

Eh bien, cela fait un moment mais je pense que c'est quelque chose comme ceci: curl.cainfo = "C: \ xampp \ cacert \ cacert.pem" et openssl.cafile = "C: \ xampp \ cacert \ cacert.pem" en php. ini, alors que je pense avoir obtenu le fichier pem d'une des réponses ici.
knezmilos

1
"Pour l'amour de tout ce qui est saint ..." en effet. Cela a fonctionné pour ma configuration Ubuntu 18.08 / Apache / Php7.2. Si l'erreur curl pointe vers le bon fichier, il s'agit très certainement de la faute openssls
JTG

4

Parfois, si l'application que vous essayez de contacter possède des certificats auto-signés, le cacert.pem normal de http://curl.haxx.se/ca/cacert.pem ne résout pas le problème.

Si vous êtes sûr de l'URL du point de terminaison du service, cliquez dessus via le navigateur, enregistrez le certificat manuellement au format "Certificat X 509 avec chaîne (PEM)". Pointez ce fichier de certificat avec le

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

4

J'ai la même erreur sur Amazon AMI Linux.

J'ai résolu en définissant curl.cainfo sur /etc/php.d/curl.ini

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

Ajout octobre 2018

Sur Amazon Linux v1, éditez ce fichier

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

Pour ajouter cette ligne

curl.cainfo="/etc/ssl/certs/ca-bundle.crt"

Parfait merci! J'ai mis à jour la question pour ajouter exactement ce que j'ai fait qui a résolu le problème pour moi, plutôt que de créer une autre réponse.
Tim

3

Lorsque vous définissez les options de boucle pour CURLOPT_CAINFO, n'oubliez pas d'utiliser des guillemets simples, l'utilisation de guillemets doubles ne provoquera qu'une autre erreur. Votre option devrait donc ressembler à:

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

De plus, dans votre fichier php.ini, le paramètre doit être écrit comme suit: (notez mes doubles guillemets)

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

Je le mets directement sous la ligne qui dit ceci: extension=php_curl.dll

(À des fins d'organisation uniquement, vous pouvez le placer n'importe où dans votre php.ini, je le mets juste à côté d'une autre référence curl, donc lorsque je recherche à l'aide du mot clé curl, je peux trouver les deux références curl dans une zone.)


1
J'espère que php.ini devrait pointer vers le fichier pem au lieu de son dossier parent
dejjub-AIS

2

Je me suis retrouvé ici en essayant d'obtenir GuzzleHttp (php + apache sur Mac) pour obtenir une page de www.googleapis.com.

Voici ma dernière solution au cas où cela aiderait quelqu'un.

Regardez la chaîne de certificats pour le domaine qui vous donne cette erreur. Pour moi, c'était googleapis.com

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

Vous récupérerez quelque chose comme ceci:

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

Remarque: J'ai capturé cela après avoir résolu le problème, la sortie de votre chaîne peut sembler différente.

Ensuite, vous devez regarder les certificats autorisés dans php. Exécutez phpinfo () dans une page.

<?php echo phpinfo();

Recherchez ensuite le fichier de certificat chargé à partir de la sortie de la page:

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

Il s'agit du fichier que vous devrez corriger en y ajoutant le ou les certificats appropriés.

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

Vous devez essentiellement ajouter les «signatures» de certificat correctes à la fin de ce fichier.

Vous pouvez en trouver certains ici: vous devrez peut-être rechercher sur Google / d'autres personnes dans la chaîne si vous en avez besoin.

Ils ressemblent à ceci:

exemple d'image de certificat

( Remarque: il s'agit d'une image afin que les gens ne copient / collent pas simplement les certificats à partir de stackoverflow )

Une fois que les bons certificats sont dans ce fichier, redémarrez apache et testez.


0

Vous pouvez essayer de réinstaller le ca-certificatespackage ou autoriser explicitement le certificat en question comme décrit ici .


-5

La solution est très simple! Mettez cette ligne avant curl_exec:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Pour moi ça marche.


7
Ne désactivez jamais la vérification par les pairs, sauf si vous ne vous souciez pas si les données sont compromises en transit.
rdlowrey

D'accord. Si vous voulez une application sécurisée, vous avez besoin d'une vérification par les pairs.
braden

2
"Ne désactivez jamais la vérification par les pairs" À MOINS que vous ne souhaitiez la fonctionnalité de navigateur par défaut haha. Aussi, pourquoi est-ce autant sous-estimé? C'est la seule réponse qui soit courte, douce, au point ET efficace.
Adam F

@AdamF FYI, les navigateurs vérifient le certificat d'homologue par défaut, ils vous donnent uniquement la possibilité de contourner les erreurs manuellement, avec un avertissement.
Bruno
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.