HTTPS und SSL3_GET_SERVER_CERTIFICATE: Zertifikatüberprüfung fehlgeschlagen, Zertifizierungsstelle ist in Ordnung


208

Ich benutze XAMPP für die Entwicklung. Kürzlich habe ich meine Installation von xampp von einer alten Version auf 1.7.3 aktualisiert.

Wenn ich jetzt HTTPS-fähige Sites locke, erhalte ich die folgende Ausnahme

Schwerwiegender Fehler: Nicht erfasste Ausnahme 'RequestCore_Exception' mit der Meldung 'cURL resource: Resource id # 55; cURL-Fehler: Problem mit dem SSL-Zertifikat. Überprüfen Sie, ob das CA-Zertifikat in Ordnung ist. Details: Fehler: 14090086: SSL-Routinen: SSL3_GET_SERVER_CERTIFICATE: Zertifikatüberprüfung fehlgeschlagen (60) '

Jeder schlägt vor, bestimmte Curl-Optionen aus PHP-Code zu verwenden, um dieses Problem zu beheben. Ich denke, das sollte nicht der Weg sein. Weil ich mit meiner alten Version von XAMPP kein Problem hatte und dies erst nach der Installation der neuen Version geschah.

Ich benötige Hilfe, um herauszufinden, welche Einstellungen sich in meiner PHP-Installation ändern. Apache usw. kann dieses Problem beheben.

Antworten:


145

Curl enthielt früher eine Liste akzeptierter Zertifizierungsstellen, bündelte jedoch keine Zertifizierungsstellenzertifikate mehr. Standardmäßig werden alle SSL-Zertifikate als nicht überprüfbar abgelehnt.

Sie müssen das Zertifikat Ihrer Zertifizierungsstelle erhalten und darauf kräuseln. Weitere Informationen finden Sie unter cURLS- Details zu Server-SSL-Zertifikaten .


4
Die Locke geschieht in der Amazon Web Services PHP-Bibliothek. Ich habe nicht verstanden, wie ich das Problem beheben kann, ohne den Bibliothekscode zu bearbeiten.
Josnidhin

41
Deaktivieren Sie dann die Zertifikatsüberprüfung ( CURLOPT_SSL_VERIFYPEER-> false). Sie fügen entweder das CA-Zertifikat der Site hinzu, mit der Sie SSL ausführen möchten, oder Sie deaktivieren die CA-Überprüfung. Dies sind die einzigen zwei verfügbaren Optionen.
Marc B

78
Nur zu Ihrer Information, CURLOPT_SSL_VERIFYPEERum falseden Zweck der Verwendung von SSL zu vereiteln.
Bis

13
@ Bis besiegt es nicht den halben Zweck von SSL? Sie erhalten immer noch Privatsphäre zwischen Ihnen und Ihrem Kollegen: Sie haben einfach keine Authentizität Ihres Kollegen.
Mark Fox

10
Was bringt es ohne Authentizität, die von Ihnen gesendeten Daten zu verschlüsseln? Wenn Sie MITMed gewesen sind, dann sind die Daten trotzdem kompromittiert
hdgarrood

290

Es ist ein ziemlich häufiges Problem in Windows. Sie müssen nur Satz cacert.pemzu curl.cainfo.

Seit PHP 5.3.7 können Sie:

  1. herunterladen https://curl.haxx.se/ca/cacert.pem und speichern Sie es irgendwo.
  2. aktualisieren php.ini - add curl.cainfo = "PATH_TO / cacert.pem"

Andernfalls müssen Sie für jede cURL-Ressource Folgendes ausführen:

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

2
Dies funktionierte für mich in XAMPP unter OS X. Es wurde ein Problem behoben, bei dem ein Wordpress-Plugin nicht aktualisiert werden konnte, weil kein lokales Zertifikat gefunden werden konnte.
Jonathan Nicol

8
Für alle anderen, die versuchten, dieses Problem unter Windows mit Apache zu lösen, musste ich den vollständigen Pfad (dh C: \ PATH_TO \ cacert.pem) in meinem PHP-Code festlegen. Auf IIS schien der relative Pfad in Ordnung zu sein.
http203

Befindet sich die Datei cacert.pem im selben Verzeichnis, dann curl_setopt ($ ch, CURLOPT_CAINFO, dirname ( FILE ). '/Cacert.pem'); wird funktionieren
Mujaffars

7
Wenn Sie WampServer mit verwenden 2., müssen Sie die Variable zwei separaten php.iniDateien hinzufügen . Siehe stackoverflow.com/a/25706713/1101095
Nate

Rätselhaft / ironisch ist, dass Sie curl.haxx.se/ca/cacert.pem über HTTPS herunterladen können, ohne zusätzliche Optionen anzugeben. Wird das Zertifikat für curl.haxx.se in curl selbst gesichert?
Qbolec

84

Warnung: Dies kann zu Sicherheitsproblemen führen, vor denen SSL schützen soll, wodurch Ihre gesamte Codebasis unsicher wird. Es widerspricht jeder empfohlenen Praxis.

Aber eine wirklich einfache Lösung, die für mich funktioniert hat, war anzurufen:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

vor dem Anruf:

curl_exec():

in der PHP-Datei.

Ich glaube, dass dies die Überprüfung von SSL-Zertifikaten deaktiviert.


65
... und wenn Sie die Überprüfung der Zertifikate deaktivieren, lassen Sie die Tür für potenzielle MITM-Angriffe offen, vor denen SSL / TLS sonst schützen möchte. TUN SIE DAS NICHT!
Bruno

12
Jep. Ich hätte in der Antwort mehr Aufmerksamkeit darauf lenken sollen. Tun Sie dies nur, wenn Sie an nichts Wichtigem arbeiten. Ich benutze es auf localhost, um auf Websites zuzugreifen, die ich persönlich programmiert habe.
Chris Dutrow

3
Ich stimme ab. Dies ist eine schmutzige Lösung, um Ihren Code zum Laufen zu bringen, aber keine Lösung. Die Antwort von Артур Курицын ist viel besser.
Ilija

2
@Bruno Dies ist die perfekte Lösung für Hilfsskripte, Tests, vertrauenswürdige Anwendungen, Intranet usw. Jeder, der ein wenig über SSL weiß, weiß, in welchen Fällen die Zertifikatsüberprüfung übersprungen werden kann. Alle 'klugen' Kommentare zu dieser Antwort und Dinge wie 'TUN SIE DAS NICHT' sind einfach UNSINN !!
Kenyakorn Ketsombut

5
... " Jeder, der ein wenig über SSL weiß [...] " ... und Sie wären überrascht, wie viele Leute sich nicht einmal die Mühe machen, ein wenig über die Grundlagen von SSL / TLS zu wissen, und kommen gerade Hier können Sie eine Schnellkorrektur für die Fehlermeldung kopieren / einfügen.
Bruno

53

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

Curl: Problem mit dem SSL-Zertifikat. Überprüfen Sie, ob das CA-Zertifikat in Ordnung ist

07. April 2006

Beim Öffnen einer sicheren URL mit Curl wird möglicherweise der folgende Fehler angezeigt:

Überprüfen Sie beim Problem mit dem SSL-Zertifikat, ob das CA-Zertifikat in Ordnung ist

Ich werde erklären, warum der Fehler und was Sie dagegen tun sollten.

Der einfachste Weg, den Fehler zu beseitigen, besteht darin, Ihrem Skript die folgenden zwei Zeilen hinzuzufügen. Diese Lösung birgt jedoch ein Sicherheitsrisiko.

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

Mal sehen, was diese beiden Parameter bewirken. Das Handbuch zitieren.

CURLOPT_SSL_VERIFYHOST : 1, um das Vorhandensein eines gemeinsamen Namens im SSL-Peer-Zertifikat zu überprüfen. 2, um das Vorhandensein eines allgemeinen Namens zu überprüfen und um sicherzustellen, dass er mit dem angegebenen Hostnamen übereinstimmt.

CURLOPT_SSL_VERIFYPEER : FALSE, um zu verhindern, dass CURL das Zertifikat des Peers überprüft. Alternative Zertifikate, gegen die geprüft werden soll, können mit der Option CURLOPT_CAINFO angegeben werden, oder ein Zertifikatverzeichnis kann mit der Option CURLOPT_CAPATH angegeben werden. CURLOPT_SSL_VERIFYHOST muss möglicherweise auch TRUE oder FALSE sein, wenn CURLOPT_SSL_VERIFYPEER deaktiviert ist (standardmäßig 2). Wenn Sie CURLOPT_SSL_VERIFYHOST auf 2 setzen (dies ist der Standardwert), wird sichergestellt, dass das Ihnen vorgelegte Zertifikat einen allgemeinen Namen hat, der mit der URN übereinstimmt, die Sie für den Zugriff auf die Remote-Ressource verwenden. Dies ist eine gesunde Prüfung, die jedoch nicht garantiert, dass Ihr Programm nicht enttäuscht wird.

Geben Sie den "Mann in der Mitte"

Ihr Programm könnte irregeführt werden, stattdessen mit einem anderen Server zu sprechen. Dies kann durch verschiedene Mechanismen erreicht werden, wie z. B. DNS oder Arp-Vergiftung (Dies ist eine Geschichte für einen anderen Tag). Der Eindringling kann auch ein Zertifikat mit demselben "Comon-Namen" selbst signieren, den Ihr Programm erwartet. Die Kommunikation wäre immer noch verschlüsselt, aber Sie würden Ihre Geheimnisse an einen Betrüger weitergeben. Diese Art von Angriff wird "Mann in der Mitte" genannt.

Den "Mann in der Mitte" besiegen

Nun, wir müssen überprüfen, ob das uns vorgelegte Zertifikat wirklich gut ist. Wir tun dies, indem wir es mit einem Zertifikat vergleichen, dem wir vernünftigerweise vertrauen.

Wenn die Remote-Ressource durch ein Zertifikat geschützt ist, das von einer der Hauptzertifizierungsstellen wie Verisign, GeoTrust et al. Ausgestellt wurde, können Sie sicher mit Mozillas Zertifizierungsstellenpaket vergleichen, das Sie unter http://curl.haxx.se/docs/caextract erhalten .html

Speichern Sie die Datei cacert.pemirgendwo auf Ihrem Server und legen Sie die folgenden Optionen in Ihrem Skript fest.

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

Informationen zu allen oben genannten Informationen finden Sie unter: http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html


38
Es wird allgemein als höflich angesehen, die Quelle Ihrer Informationen anzugeben und nur bestimmte Teile zu zitieren, die für die Frage relevant sind, anstatt sie hier einfach zu kopieren und einzufügen!
Dan Herd

1
Entschuldigung, ich war weg, ja, ich schätze Dan dafür und aktualisiere den Beitrag
Deepak Oberoi

6
Zumindest machte sich Deepak die Mühe, es zu erforschen. @danherd Also danherd, du hast gerade nachgeforscht, um herauszufinden, dass er den Code von irgendwoher genommen hat? Was war das Zuordnungsrecht dieses Codes? Anstatt Ihre Zeit damit zu verschwenden, Fehler anderer zu finden, versuchen Sie, jemandem selbst zu helfen. Kämpfe nicht, teile!
GTodorov

17

Die oben genannten Lösungen sind großartig, aber wenn Sie WampServer verwenden, funktioniert das Einstellen der curl.cainfoVariablen möglicherweise php.ininicht.

Ich fand schließlich heraus, dass WampServer zwei php.iniDateien hat:

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

Die erste wird anscheinend verwendet, wenn PHP-Dateien über einen Webbrowser aufgerufen werden, während die zweite verwendet wird, wenn ein Befehl über die Befehlszeile oder aufgerufen wird shell_exec().

TL; DR

Wenn Sie WampServer verwenden, müssen Sie die curl.cainfoZeile zu beiden php.ini Dateien hinzufügen .


6

Für die Liebe von allem, was heilig ist ...

In meinem Fall musste ich die openssl.cafilePHP-Konfigurationsvariable auf den PEM-Dateipfad setzen.

Ich vertraue darauf, dass es sehr viele Systeme gibt, in denen die Einstellung curl.cainfoin der PHP-Konfiguration genau das ist, was benötigt wird, aber in der Umgebung, mit der ich arbeite, ist dies der Docker-Container eboraas / laravel , der Debian 8 (jessie) und PHP verwendet 5.6, das Setzen dieser Variablen hat den Trick nicht getan.

Ich bemerkte, dass die Ausgabe von php -inichts über diese bestimmte Konfigurationseinstellung erwähnte, aber es gab ein paar Zeilen darüber openssl. Es gibt sowohl eine openssl.capathals auch eine openssl.cafileOption, aber nur das Einstellen der zweiten Option ermöglichte das Einrollen über PHP, damit HTTPS-URLs endlich in Ordnung sind.


Danke dir! Das Einstellen von curl.cainfo hat auch bei mir nicht funktioniert, das Einstellen von openssl.cafile jedoch! Ich bin auf Windows 7 mit XAMPP und PHP 7.1.1.
Knezmilos

@knezmilos Wie haben Sie die openssl.cafile eingestellt? Wo haben Sie heruntergeladen und wie aktivieren Sie es?
Krys

Nun, es ist eine Weile her, aber ich denke, es ist ungefähr so: curl.cainfo = "C: \ xampp \ cacert \ cacert.pem" und openssl.cafile = "C: \ xampp \ cacert \ cacert.pem" in PHP. ini, während ich glaube, ich habe die PEM-Datei von einer der Antworten hier bekommen.
Knezmilos

1
"Aus Liebe zu allem, was heilig ist ..." in der Tat. Dies funktionierte für mein Ubuntu 18.08 / Apache / Php7.2-Setup. Wenn der Curl-Fehler auf die richtige Datei zeigt, dann ist es mit Sicherheit ein OpenSLS-Fehler
JTG

4

Manchmal, wenn die Anwendung, mit der Sie Kontakt aufnehmen möchten, selbstsignierte Zertifikate hat, löst das normale cacert.pem von http://curl.haxx.se/ca/cacert.pem das Problem nicht.

Wenn Sie sich über die Service-Endpunkt-URL sicher sind, rufen Sie sie über den Browser auf und speichern Sie das Zertifikat manuell im Format "X 509-Zertifikat mit Kette (PEM)". Zeigen Sie auf diese Zertifikatdatei mit dem

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

4

Ich habe den gleichen Fehler unter Amazon AMI Linux.

Ich habe gelöst, indem ich curl.cainfo auf /etc/php.d/curl.ini gesetzt habe

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

Ergänzung Oktober 2018

Bearbeiten Sie diese Datei unter Amazon Linux v1

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

Diese Zeile hinzufügen

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

Perfekt danke! Ich habe die Frage aktualisiert, um genau das hinzuzufügen, was ich getan habe, um das Problem für mich zu lösen, anstatt eine andere Antwort zu erstellen.
Tim

3

Denken Sie beim Festlegen der Curl-Optionen für CURLOPT_CAINFO daran, einfache Anführungszeichen zu verwenden. Die Verwendung von doppelten Anführungszeichen führt nur zu einem weiteren Fehler. Ihre Option sollte also folgendermaßen aussehen:

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

Außerdem sollte in Ihrer php.ini-Datei die Einstellung wie folgt geschrieben sein: (Beachten Sie meine doppelten Anführungszeichen)

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

Ich setze es direkt unter die Zeile, die dies sagt: extension=php_curl.dll

(Nur zu Organisationszwecken können Sie es an einer beliebigen Stelle in Ihrem php.iniBereich platzieren. Ich platziere es einfach in der Nähe einer anderen Curl-Referenz. Wenn ich also mit dem Schlüsselwort curl suche, kann ich beide Curl-Referenzen in einem Bereich finden.)


1
Ich hoffe, php.ini sollte auf die PEM-Datei anstelle des übergeordneten Ordners
verweisen

2

Ich bin hier gelandet, als ich versucht habe, GuzzleHttp (PHP + Apache auf Mac) dazu zu bringen, eine Seite von www.googleapis.com zu erhalten.

Hier war meine endgültige Lösung für den Fall, dass es jemandem hilft.

Überprüfen Sie die Zertifikatkette auf die Domain, bei der dieser Fehler auftritt. Für mich war es googleapis.com

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

Sie erhalten so etwas zurück:

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

Hinweis: Ich habe dies erfasst, nachdem ich das Problem behoben habe. Ihre Kettenausgabe sieht möglicherweise anders aus.

Dann müssen Sie sich die in PHP erlaubten Zertifikate ansehen. Führen Sie phpinfo () auf einer Seite aus.

<?php echo phpinfo();

Suchen Sie dann nach der Zertifikatdatei, die aus der Seitenausgabe geladen wurde:

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

Dies ist die Datei, die Sie reparieren müssen, indem Sie die richtigen Zertifikate hinzufügen.

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

Grundsätzlich müssen Sie die richtigen Zertifikatsignaturen an das Ende dieser Datei anhängen.

Einige davon finden Sie hier: Möglicherweise müssen Sie andere in der Kette googeln / suchen, wenn Sie sie benötigen.

Sie sehen so aus:

Beispiel für ein Zertifikatbild

( Hinweis: Dies ist ein Bild, damit Benutzer nicht einfach Zertifikate aus dem Stapelüberlauf kopieren / einfügen. )

Sobald sich die richtigen Zertifikate in dieser Datei befinden, starten Sie Apache neu und testen Sie.


0

Sie können versuchen, das ca-certificatesPaket neu zu installieren , oder das betreffende Zertifikat explizit zulassen, wie hier beschrieben .


-5

Die Lösung ist sehr einfach! Setzen Sie diese Zeile vor curl_exec:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Bei mir funktioniert es.


7
Nie, nie deaktivieren Peer Prüfung nur , wenn Sie es egal, ob die Daten während der Übertragung beeinträchtigt werden.
Rdlowrey

Einverstanden. Wenn Sie eine sichere App wünschen, benötigen Sie eine Peer-Überprüfung.
Braden

2
"Deaktivieren Sie niemals die Peer-Überprüfung", es sei denn, Sie möchten Standard-Browserfunktionen, haha. Warum wird das so sehr herabgestimmt? Dies ist die einzige Antwort, die kurz, süß, auf den Punkt und effektiv ist.
Adam F

@AdamF FYI, Browser überprüfen standardmäßig das Peer-Zertifikat. Sie bieten Ihnen nur die Möglichkeit, Fehler manuell mit einer Warnung zu umgehen.
Bruno
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.