HTTPS e SSL3_GET_SERVER_CERTIFICATE: falha na verificação do certificado, CA está OK


208

Estou usando o XAMPP para desenvolvimento. Recentemente, atualizei minha instalação do xampp de uma versão antiga para a 1.7.3.

Agora, quando enrolado sites habilitados para HTTPS, recebo a seguinte exceção

Erro fatal: exceção não capturada 'RequestCore_Exception' com a mensagem 'recurso cURL: ID do recurso # 55; Erro cURL: problema no certificado SSL, verifique se o certificado da CA está OK. Detalhes: erro: 14090086: rotinas SSL: SSL3_GET_SERVER_CERTIFICATE: falha na verificação do certificado (60) '

Todos sugerem o uso de algumas opções específicas de curl do código PHP para corrigir esse problema. Eu acho que não deveria ser assim. Porque não tive nenhum problema com a minha versão antiga do XAMPP e só aconteceu depois de instalar a nova versão.

Preciso de ajuda para descobrir quais configurações são alteradas na minha instalação do PHP, Apache etc. podem corrigir esse problema.

Respostas:


145

o curl costumava incluir uma lista de CAs aceitas, mas não agrupa mais QUALQUER certificado de CA. Portanto, por padrão, rejeitará todos os certificados SSL como não verificáveis.

Você precisará obter o certificado da CA e apontar ondulações para ele. Mais detalhes em Detalhes do cURLS sobre certificados SSL do servidor .


4
A onda está acontecendo na biblioteca php de serviços web da Amazon. Não entendi como corrigi-lo sem editar o código da biblioteca.
— 21711 Josnidhin

41
Em seguida, desative a verificação do certificado ( CURLOPT_SSL_VERIFYPEER-> false). Você pode adicionar o certificado de CA do site com o qual está tentando fazer SSL ou desabilitar a verificação da CA. Essas são as duas únicas opções disponíveis.
— Marc B

78
Apenas fyi - configuração CURLOPT_SSL_VERIFYPEERpara falseanula o propósito de usar SSL.
— Até

13
@ Até que não derrote metade da finalidade do SSL? Você ainda tem privacidade entre você e seu colega: você simplesmente não tem autenticidade.
— Mark Fox

10
sem autenticidade, qual é o sentido de criptografar os dados que você está enviando? Se você tiver sido MITMed seguida, os dados é comprometida de qualquer maneira
— hdgarrood

290

É um problema bastante comum no Windows. Você precisa apenas definir cacert.pemcomo curl.cainfo.

Desde o PHP 5.3.7, você pode fazer:

  1. faça o download de https://curl.haxx.se/ca/cacert.pem e salve-o em algum lugar.
  2. atualização php.ini- add curl.cainfo = "PATH_TO / cacert.pem"

Caso contrário, você precisará fazer o seguinte para cada recurso cURL:

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

2
Isso funcionou para mim no XAMPP no OS X. Foi corrigido um problema em que um plugin do Wordpress não era atualizado devido à impossibilidade de localizar um certificado local.
— Jonathan Nicol

8
Para qualquer outra pessoa que tente resolver esse problema no Windows usando o Apache, tive que definir o caminho completo (por exemplo, C: \ PATH_TO \ cacert.pem) no meu código PHP. No IIS, o caminho relativo parecia funcionar bem.
— http203

Se o cacert.pem estiver no mesmo diretório, então curl_setopt ($ ch, CURLOPT_CAINFO, dirname ( FILE ). '/Cacert.pem'); funcionará
— mujaffars

7
Ao usar o WampServer com 2., você deve adicionar a variável a dois php.iniarquivos separados . Veja stackoverflow.com/a/25706713/1101095
— Nate

O que é intrigante / irônico é que você pode fazer o download do curl.haxx.se/ca/cacert.pem através de HTTPS sem especificar opções adicionais. O certificado do curl.haxx.se foi copiado para o próprio curl?
— 22416 qbolec

84

Aviso: isso pode apresentar problemas de segurança contra os quais o SSL foi projetado para proteger, tornando toda a sua base de código insegura. Isso vai contra todas as práticas recomendadas.

Mas uma correção realmente simples que funcionou para mim foi chamar:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

antes de ligar para:

curl_exec():

no arquivo php.

Acredito que isso desabilite toda a verificação de certificados SSL.


65
... e desativando a verificação dos certificados, você deixa a porta aberta para possíveis ataques MITM, contra os quais o SSL / TLS visa proteger. NÃO FAÇA ISTO!
— Bruno

12
Sim. Eu deveria ter chamado mais atenção para isso na resposta. Faça isso apenas se você não estiver trabalhando em algo importante. Eu o uso no host local para acessar sites que eu pessoalmente programei.
— Chris Dutrow

3
Voto negativo de mim. Esta é uma correção suja para que seu código funcione, mas não uma solução. A resposta fornecida por Артур Курицын é muito melhor.
— precisa

2
@Bruno Esta é a solução perfeita, para scripts auxiliares, testes, aplicativos confiáveis, intranet, ..... Todo mundo que conhece POUCO SOBRE SSL, sabe em quais casos a validação de certificado pode ser ignorada. Portanto, todos os comentários 'inteligentes' sobre esta resposta e coisas como 'NÃO FAÇA ISSO' são apenas um absurdo!
— Kenyakorn Ketsombut 13/03/2015

5
... " Todo mundo que conhece UM POUCO sobre SSL [...] " ... e você ficaria surpreso com quantas pessoas nem se importam em saber um pouco sobre o básico do SSL / TLS e estão chegando. aqui para copiar / colar uma correção rápida para a mensagem de erro.
— de Bruno

53

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

Problema no certificado SSL: verifique se o certificado da CA está OK

07 de abril de 2006

Ao abrir um URL seguro com o Curl, você pode receber o seguinte erro:

Problema no certificado SSL, verifique se o certificado da CA está OK

Vou explicar por que o erro e o que você deve fazer sobre isso.

A maneira mais fácil de se livrar do erro seria adicionar as duas linhas a seguir ao seu script. Esta solução apresenta um risco de segurança.

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

Vamos ver o que esses dois parâmetros fazem. Citando o manual.

CURLOPT_SSL_VERIFYHOST : 1 para verificar a existência de um nome comum no certificado de mesmo nível SSL. 2 para verificar a existência de um nome comum e também verificar se ele corresponde ao nome do host fornecido.

CURLOPT_SSL_VERIFYPEER : FALSE para impedir que CURL verifique o certificado do par. Certificados alternativos para verificação podem ser especificados com a opção CURLOPT_CAINFO ou um diretório de certificado pode ser especificado com a opção CURLOPT_CAPATH. Talvez CURLOPT_SSL_VERIFYHOST também precise ser TRUE ou FALSE se CURLOPT_SSL_VERIFYPEER estiver desativado (o padrão é 2). Definir CURLOPT_SSL_VERIFYHOST como 2 (este é o valor padrão) garantirá que o certificado que está sendo apresentado a você tenha um 'nome comum' correspondente ao URN que você está usando para acessar o recurso remoto. Esta é uma verificação saudável, mas não garante que o seu programa não está sendo enganado.

Digite o 'homem do meio'

Seu programa pode ser enganado ao conversar com outro servidor. Isso pode ser conseguido através de vários mecanismos, como DNS ou envenenamento por arp (esta é uma história para outro dia). O invasor também pode autoassinar um certificado com o mesmo 'nome comum' que seu programa está esperando. A comunicação ainda seria criptografada, mas você revelaria seus segredos a um impostor. Esse tipo de ataque é chamado de 'homem do meio'

Derrotar o 'homem do meio'

Bem, precisamos verificar se o certificado que está sendo apresentado para nós é bom de verdade. Fazemos isso comparando-o com um certificado em que razoavelmente * confiamos.

Se o recurso remoto estiver protegido por um certificado emitido por uma das principais autoridades de certificação como Verisign, GeoTrust et al, você poderá comparar com segurança o pacote de certificados de autoridade de certificação da Mozilla, que pode obter em http://curl.haxx.se/docs/caextract .html

Salve o arquivo cacert.pemem algum lugar do seu servidor e defina as seguintes opções no seu script.

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

para Tudo acima Informações de crédito Vá para: http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html


38
Geralmente, é educado creditar a fonte de suas informações e citar apenas certas partes relevantes para a pergunta, em vez de simplesmente copiar e colar aqui!
— Dan Herd

1
Desculpe, eu estive fora, sim, eu apregoo Dan para isso e atualizei o Post
— Deepak Oberoi

6
Pelo menos Deepak fez um esforço para pesquisá-lo. @danherd Então, Danherd, você acabou de fazer a pesquisa para descobrir que ele pegou o código de algum lugar? Qual era o direito de atribuição deste código? Em vez de desperdiçar seu tempo para encontrar os erros de outra pessoa, tente ajudar alguém sozinho. Não lute, compartilhe!
— GTodorov

17

As soluções acima são ótimas, mas se você estiver usando o WampServer, poderá achar que a configuração da curl.cainfovariável php.ininão funciona.

Acabei encontrando o WampServer com dois php.iniarquivos:

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

O primeiro é aparentemente usado para quando arquivos PHP são chamados por meio de um navegador da Web, enquanto o segundo é usado quando um comando é chamado por meio da linha de comando ou shell_exec().

TL; DR

Se estiver usando o WampServer, você deve adicionar a curl.cainfolinha aos dois php.ini arquivos.


6

Pelo amor de tudo o que é santo ...

No meu caso, eu tive que definir o openssl.cafile variável de configuração PHP para o caminho do arquivo PEM.

Confio que é verdade que existem muitos sistemas em que a configuração curl.cainfona configuração do PHP é exatamente o que é necessário, mas no ambiente com o qual estou trabalhando, que é o eboraas / laravel docker, que usa Debian 8 (jessie) e PHP 5.6, definir essa variável não funcionou.

Percebi que a saída de php -inão mencionou nada sobre essa configuração específica, mas havia algumas linhas openssl. Há uma opção openssl.capathe openssl.cafile, mas apenas definir a segunda opção permitida via PHP para finalmente ficar bem com os URLs HTTPS.


Obrigado! Definir o curl.cainfo também não funcionou para mim, mas definir o openssl.cafile funcionou! Estou no Windows 7 com XAMPP e PHP 7.1.1.
— knezmilos

@knezmilos, como você definiu o openssl.cafile? onde você baixou e como ativá-lo?
— Krypton #

Bem, já faz um tempo, mas acho que é algo assim: curl.cainfo = "C: \ xampp \ cacert \ cacert.pem" e openssl.cafile = "C: \ xampp \ cacert \ cacert.pem" no php. ini, enquanto acho que obtive o arquivo pem de uma das respostas aqui.
— Knezmilos

1
"Pelo amor de tudo o que é santo ..." de fato. Isso funcionou para a minha instalação do Ubuntu 18.08 / Apache / Php7.2. Se o erro onda está apontando para o arquivo correto, então ele certamente é culpa openssls
— JTG

4

Às vezes, se o aplicativo que você tentar entrar em contato tiver certificados autoassinados, o cacert.pem normal em http://curl.haxx.se/ca/cacert.pem não resolverá o problema.

Se você tiver certeza do URL do terminal em serviço, acesse-o pelo navegador, salve o certificado manualmente no formato "Certificado X 509 com cadeia (PEM)". Aponte este arquivo de certificado com o

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

4

Eu tenho o mesmo erro no Amazon AMI linux.

Resolvi definindo curl.cainfo em /etc/php.d/curl.ini

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

Adição outubro 2018

No Amazon Linux v1, edite este arquivo

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

Para adicionar esta linha

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

Perfeito, obrigado! Atualizei a pergunta para adicionar exatamente o que fiz e resolvi o problema para mim, em vez de criar outra resposta.
— Tim

3

Ao definir as opções de curvatura para CURLOPT_CAINFO, lembre-se de usar aspas simples, usar aspas duplas causará apenas outro erro. Portanto, sua opção deve se parecer com:

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

Além disso, no seu arquivo php.ini, a configuração deve ser escrita como: (observe minhas aspas duplas)

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

Coloquei diretamente abaixo da linha que diz o seguinte: extension=php_curl.dll

(Apenas para fins de organização, você pode colocá-lo em qualquer lugar dentro do seu php.ini, basta colocá-lo perto de outra referência de ondulação; portanto, quando procuro usando a palavra-chave ondulação, posso encontrar as duas referências de ondulação em uma área.)


1
Espero php.ini deve apontar para o arquivo pem vez de sua pasta pai
— dejjub-AIS

2

Acabei aqui ao tentar obter o GuzzleHttp (php + apache no Mac) para obter uma página em www.googleapis.com.

Aqui estava minha solução final, caso isso ajude alguém.

Examine a cadeia de certificados para qualquer domínio que esteja fornecendo esse erro. Para mim, foi googleapis.com

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

Você receberá algo como isto:

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: Eu capturei isso depois de corrigir o problema. A saída da sua cadeia pode parecer diferente.

Então você precisa olhar para os certificados permitidos no php. Execute phpinfo () em uma página.

<?php echo phpinfo();

Em seguida, procure o arquivo de certificado carregado na saída da página:

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

Esse é o arquivo que você precisará corrigir adicionando os certificados corretos.

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

Basicamente, você precisa anexar as "assinaturas" corretas do certificado ao final deste arquivo.

Você pode encontrar alguns deles aqui: talvez seja necessário pesquisar no google / outros na cadeia, se você precisar deles.

Eles se parecem com isso:

imagem de certificado de exemplo

( Nota: Esta é uma imagem para que as pessoas não copiem / colem simplesmente certificados do stackoverflow )

Quando os certificados corretos estiverem nesse arquivo, reinicie o apache e teste.


0

Você pode tentar reinstalar o ca-certificatespacote ou permitir explicitamente o certificado em questão, conforme descrito aqui .


-5

A solução é muito simples! Coloque esta linha antes curl_exec:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Para mim funciona.


7
Nunca, jamais desative a verificação por pares, a menos que você não se importe se os dados estiverem comprometidos em trânsito.
— precisa saber é o seguinte

Acordado. Se você deseja um aplicativo seguro, precisa da verificação por pares.
— 22814

2
"Nunca desative a verificação por pares", a menos que você queira a funcionalidade padrão do navegador, haha. Além disso, por que isso é tão prejudicado? Esta é a única resposta que é curta, doce, ao ponto E eficaz.
— 23714 Adam

@AdamF FYI, os navegadores verificam o certificado de mesmo nível, por padrão, eles oferecem a opção de ignorar erros manualmente, com um aviso.
— 224 Bruno
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.