HTTPS та SSL3_GET_SERVER_CERTIFICATE: перевірка сертифікату не вдалася, CA - це нормально


208

Я використовую XAMPP для розробки. Нещодавно я модернізував встановлення xampp зі старої версії до 1.7.3.

Тепер, коли я згортаю HTTPS-сайти, я отримую наступне виняток

Фатальна помилка: Невизначений виняток 'RequestCore_Exception' з повідомленням 'ресурс cURL: ідентифікатор ресурсу №55; помилка cURL: проблема з сертифікатом SSL, перевірте, чи підтверджено сертифікат CA. Деталі: помилка: 14090086: Підпрограми SSL: SSL3_GET_SERVER_CERTIFICATE: помилка перевірки сертифікату (60) '

Для вирішення цієї проблеми кожен пропонує використовувати деякі конкретні варіанти завивки з PHP-коду. Я думаю, що це не повинно бути так. Тому що у мене не було жодної проблеми зі старою версією XAMPP, і це сталося лише після встановлення нової версії.

Мені потрібна допомога, щоб з’ясувати, які налаштування змінюються в моїй установці PHP, Apache тощо може вирішити цю проблему.

Відповіді:


145

curl використовується для включення списку прийнятих ЦС, але більше не зв'язує КОЖНІ СЕРТИ. Тож за замовчуванням він відхиляє всі сертифікати SSL як неперевірені.

Вам доведеться дістати сертифікат вашої організації і вказувати на нього. Більш детальна інформація у cURLS Деталі про сертифікати SSL сервера .


4
Завивка відбувається в php-бібліотеці веб-служб Amazon. Я не зрозумів, як це виправити без редагування коду бібліотеки.
Йоснідхін

41
Потім вимкніть перевірку сертифіката ( CURLOPT_SSL_VERIFYPEER-> false). Ви або додасте сертифікат CA на веб-сайт, з яким ви намагаєтеся зробити SSL, або вимкніть версію CA. Це єдині два доступні варіанти.
Марк Б

78
Просто fyi - налаштування, CURLOPT_SSL_VERIFYPEERщоб falseперемогти мету використання SSL.
До

13
@Тільки це не переможе половину мети SSL? Ви все ще отримуєте конфіденційність між вами та вашим ровесником: у вас просто немає автентичності вашого однолітка.
Марк Фокс

10
без автентичності, який сенс шифрувати дані, які ви надсилаєте? Якщо ви були MITMed, то дані все одно
порушені

290

Це досить поширена проблема в Windows. Вам потрібно просто набір cacert.pemдо curl.cainfo.

З PHP 5.3.7 ви можете:

  1. завантажити https://curl.haxx.se/ca/cacert.pem і зберегти його кудись.
  2. оновлення php.ini- додайте curl.cainfo = "PATH_TO / cacert.pem"

Інакше вам потрібно буде виконати наступне для кожного ресурсу CURL:

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

2
Це працювало для мене в XAMPP на OS X. Він вирішив проблему, коли плагін Wordpress не оновлювався через те, що не вдалося знайти локальний сертифікат.
Джонатан Нікол

8
Для всіх, хто намагається вирішити цю проблему в Windows за допомогою Apache, мені довелося встановити повний шлях (тобто C: \ PATH_TO \ cacert.pem) у своєму PHP-коді. На IIS відносний шлях, здається, працює нормально.
http203

Якщо cacert.pem знаходиться в одному каталозі, тоді curl_setopt ($ ch, CURLOPT_CAINFO, dirname ( FILE ). '/Cacert.pem'); працюватимуть
моджафари

7
Під час використання WampServer 2., ви повинні додати змінну до двох окремих php.iniфайлів. Дивіться stackoverflow.com/a/25706713/1101095
Нейт

Дивовижне / іронічне - це те, що ви можете завантажити curl.haxx.se/ca/cacert.pem через HTTPS, не вказуючи додаткових опцій. Чи резервний сертифікат на curl.haxx.se резервується в curl?
qbolec

84

Попередження: це може спричинити проблеми безпеки, від яких SSL призначений для захисту, і зробить вашу всю кодову базу незахищеною. Це суперечить кожній рекомендованій практиці.

Але дійсно просте виправлення, яке працювало для мене, було викликати:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

перед тим, як зателефонувати:

curl_exec():

у файлі php.

Я вважаю, що це відключає всю перевірку сертифікатів SSL.


65
... і відключивши перевірку сертифікатів, ви залишаєте двері відкритими для можливих атак MITM, від яких SSL / TLS інакше має на меті захист. НЕ робіть цього!
Бруно

12
Так. Я мав би звернути на це більше уваги у відповіді. Робіть це лише якщо ви не працюєте над будь-яким важливим. Я використовую його у localhost для доступу до веб-сайтів, які я особисто запрограмував.
Кріс Датроу

3
Від мене зворотний голос. Це брудне виправлення для роботи коду, але не рішення. Відповідь Артура Курицын набагато краща.
Ілля

2
@Bruno Це ідеальне рішення для помічників, тестів, довірених програм, інтрамережі, ..... Кожен, хто знає МАЛКО про SSL, знає, у яких випадках перевірку сертифікату можна пропустити. Тож усі "розумні" коментарі до цієї відповіді та такі речі, як "НЕ РОБИТИ ЦЕ", - це просто НУЩА !!
Kenyakorn Ketsombut

5
... " Усі, хто знає МАЛО про SSL [...] " ... і ти здивуєшся, скільки людей навіть не турбуються, знаючи трохи про основи SSL / TLS, а просто приходять тут скопіюйте та вставте швидке виправлення повідомлення про помилку.
Бруно

53

Джерело: http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html

Curl: Проблема з сертифікатом SSL, перевірте, чи підтверджено сертифікат CA

07 квітня 2006 року

Під час відкриття захищеної URL-адреси за допомогою Curl ви можете отримати таку помилку:

Проблема з сертифікатом SSL, перевірте, чи підтверджено сертифікат CA

Я поясню, чому помилка і що з цим ви повинні зробити.

Найпростішим способом позбавлення від помилки було б додавання наступних двох рядків до вашого сценарію. Це рішення становить загрозу безпеці.

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

Давайте подивимося, що роблять ці два параметри. Цитуючи посібник.

CURLOPT_SSL_VERIFYHOST : 1, щоб перевірити наявність загального імені в сертифікаті однорангових SSL. 2, щоб перевірити наявність загального імені, а також переконатися, що воно відповідає вказаному імені хоста.

CURLOPT_SSL_VERIFYPEER : FALSE, щоб зупинити CURL від перевірки сертифікату однолітків. Альтернативні сертифікати, для підтвердження яких можна встановити, можна вказати за допомогою параметра CURLOPT_CAINFO або каталог сертифікатів можна вказати за допомогою параметра CURLOPT_CAPATH. CURLOPT_SSL_VERIFYHOST також може бути TRUE або FALSE, якщо CURLOPT_SSL_VERIFYPEER вимкнено (за замовчуванням до 2). Якщо встановити значення CURLOPT_SSL_VERIFYHOST на 2 (це значення за замовчуванням), гарантується, що представлений вам сертифікат має "загальне ім'я", що відповідає URN, який ви використовуєте для доступу до віддаленого ресурсу. Це корисна перевірка, але це не гарантує, що ваша програма не буде сприйнята.

Введіть "людина посередині"

Ваша програма може бути введена в оману в розмові з іншим сервером. Цього можна досягти за допомогою декількох механізмів, як отруєння dns або arp (це історія для іншого дня). Зловмисник також може самостійно підписати сертифікат з тим самим «ім'ям комуна», який очікує ваша програма. Комунікація все ще буде зашифрована, але ви передасте свої таємниці самозванець. Такий напад називається "людина посередині"

Перемога над "людиною посередині"

Ну, нам потрібно перевірити, чи представлений нам сертифікат є справжнім. Ми робимо це, порівнюючи його з сертифікатом, якому ми довіряємо *.

Якщо віддалений ресурс захищений сертифікатом, виданим одним із основних CA, таких як Verisign, GeoTrust та ін., Ви можете сміливо порівнювати з пакетом сертифікатів Mozilla CA, який ви можете отримати з http://curl.haxx.se/docs/caextract .html

Збережіть файл cacert.pemдесь на вашому сервері та встановіть у вашому сценарії наступні параметри.

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

Інформація про все вищезазначене Кредит: http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html


38
Зазвичай вважається ввічливим зараховувати джерело вашої інформації та цитувати лише певні частини, що стосуються питання, а не просто копіювати та вставляти сюди!
Ден Герд

1
Вибачте, я був у гостях, так, я вручаю Дену за це та оновив повідомлення
Deepak Oberoi

6
Принаймні, Діпак доклав зусиль для його дослідження. @danherd Отже, danherd, ви просто зробили дослідження, щоб виявити, що він взяв код звідкись? Яке право було на атрибуцію цього коду? Замість того, щоб витрачати свій час на пошук чужих помилок, спробуйте допомогти комусь самостійно. Не бійтеся, діліться!
Гтодоров

17

Вищезазначені рішення є чудовими, але якщо ви використовуєте WampServer, можливо, встановлення curl.cainfoзмінної php.iniне працює.

Зрештою я виявив, що WampServer має два php.iniфайли:

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

Перший, мабуть, використовується, коли файли PHP викликаються через веб-браузер, а другий використовується, коли команда викликається через командний рядок або shell_exec().

TL; DR

Якщо ви використовуєте WampServer, ви повинні додати curl.cainfoрядок до обох php.ini файлів.


6

За любов до всього, що святе ...

У моєму випадку мені довелося встановити openssl.cafileзмінну конфігурації PHP на шлях файлу PEM.

Я вірю, що це дуже правда, що існує багато систем, де налаштування curl.cainfoв конфігурації PHP - саме те, що потрібно, але в середовищі, з яким я працюю, це контейнер докерів eboraas / laravel , який використовує Debian 8 (jessie) та PHP 5.6, встановивши цю змінну, це не зробило хитрощів.

Я помітив, що у висновку php -iнічого не згадується про цю конкретну конфігураційну настройку, але вона мала кілька рядків openssl. Є openssl.capathі openssl.cafileопція, і варіант, але просто встановлення другого дозволеного згортання через PHP, щоб, нарешті, було добре з URL-адресами HTTPS.


Дякую! Налаштування curl.cainfo також не працювало для мене, але налаштування openssl.cafile зробила! Я в Windows 7 з XAMPP і PHP 7.1.1.
knezmilos

@knezmilos як ти вирішив налаштувати файл openssl.cafile? де ви завантажили і як його активувати?
Крис

Ну, пройшов час, але я думаю, що це приблизно так: curl.cainfo = "C: \ xampp \ cacert \ cacert.pem" і openssl.cafile = "C: \ xampp \ cacert \ cacert.pem" у php. ini, хоча я думаю, що я отримав файл pem з однієї з відповідей тут.
knezmilos

1
"Бо любов до всього, що святе ..." справді. Це працювало для моєї установки Ubuntu 18.08 / Apache / Php7.2. Якщо помилка локон вказує на правильний файл, то це, безумовно , є openssls вина
ОСГ

4

Іноді, якщо програма, до якої ви намагаєтеся зв’язатися, має сертифікати самопідписаних, звичайна cacert.pem від http://curl.haxx.se/ca/cacert.pem не вирішує проблему.

Якщо ви впевнені в URL-адресі кінцевої точки служби, натисніть її через браузер, збережіть сертифікат вручну у форматі "Сертифікат X 509 з ланцюгом (PEM)". Наведіть цей файл сертифіката на

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

4

У мене така ж помилка на Amazon AMI linux.

Я вирішив, встановивши curl.cainfo на /etc/php.d/curl.ini

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

Доповнення жовтня 2018 року

На Amazon Linux v1 відредагуйте цей файл

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

Щоб додати цей рядок

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

Ідеально, дякую! Я оновив питання, щоб додати саме те, що робив, що вирішив проблему для мене, а не створив іншу відповідь.
Тім

3

Встановлюючи параметри завитка для CURLOPT_CAINFO, будь ласка, пам’ятайте про використання одинарних лапок, використання подвійних лапок призведе лише до іншої помилки. Отже, ваш варіант повинен виглядати так:

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

Крім того, у вашому налаштуваннях файлу php.ini слід записати так: (зверніть увагу на мої подвійні лапки)

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

Я розміщую це прямо під рядком, який говорить про це: extension=php_curl.dll

(Тільки для організаційних цілей ви можете розмістити його в будь-якому місці в межах свого php.ini, я просто покладу його близько до іншої посилання на завиток, тому при пошуку за ключовим словом curl я можу знайти обидві посилання на curl в одній області.)


1
Я сподіваюся, що php.ini має вказати на файл pem замість його батьківської папки
dejjub-AIS

2

Я опинився тут, намагаючись отримати GuzzleHttp (php + apache на Mac), щоб отримати сторінку з www.googleapis.com.

Ось моє остаточне рішення на випадок, якщо воно допомагає комусь.

Подивіться на ланцюжок сертифікатів для будь-якого домену, який дає вам цю помилку. Для мене це був googleapis.com

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

Ви отримаєте щось таке:

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

Примітка. Я зафіксував це після того, як вирішив проблему, щоб ваш вихід ланцюга може виглядати інакше.

Потім потрібно подивитися сертифікати, дозволені в php. Запустіть phpinfo () на сторінці.

<?php echo phpinfo();

Потім шукайте файл сертифіката, завантажений із сторінки виводу:

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

Це файл, який потрібно буде виправити, додавши до нього правильні сертифікати.

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

В основному вам потрібно додати правильні "підписи" до кінця цього файлу.

Деякі з них можна знайти тут: Можливо, вам знадобиться google / пошук інших у ланцюжку, якщо вони вам потрібні.

Вони виглядають так:

Приклад зображення сертифіката

( Примітка. Це зображення, щоб люди не просто копіювали / вставляли сертифікати з stackoverflow )

Як тільки потрібні сертифікати знаходяться у цьому файлі, перезапустіть apache та тестуйте.


0

Ви можете спробувати перевстановити ca-certificatesпакет або явно дозволити відповідний сертифікат, як описано тут .


-5

Рішення дуже просте! Поставте цей рядок раніше curl_exec:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Для мене це працює.


7
Ніколи, ніколи не вимикайте перевірку однолітків, якщо вам не байдуже, якщо дані порушені під час транзиту.
rdlowrey

Домовились. Якщо ви хочете захистити надійну програму, вам потрібна перевірка рівних.
braden

2
"Ніколи, ніколи не вимикайте перевірку рівних". ПІДНЯТЬ, якщо ви хочете використовувати функціональність браузера за замовчуванням Крім того, чому це так заборонено? Це єдина відповідь, яка коротка, мила, до речі І дієва.
Адам Ф

@AdamF FYI, браузери НЕ перевіряють сертифікат рівних за замовчуванням, вони дають лише можливість обминати помилки вручну, з попередженням.
Бруно
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.