Exibindo detalhes de um certificado SSL remoto usando ferramentas da CLI

187

No Chrome, clicar no ícone verde de bloqueio HTTPS abre uma janela com os detalhes do certificado:

insira a descrição da imagem aqui

Quando tentei o mesmo com o cURL, obtive apenas algumas das informações:

$ curl -vvI https://gnupg.org
* Rebuilt URL to: https://gnupg.org/
* Hostname was NOT found in DNS cache
*   Trying 217.69.76.60...
* Connected to gnupg.org (217.69.76.60) port 443 (#0)
* TLS 1.2 connection using TLS_DHE_RSA_WITH_AES_128_CBC_SHA
* Server certificate: gnupg.org
* Server certificate: Gandi Standard SSL CA
* Server certificate: UTN-USERFirst-Hardware
> HEAD / HTTP/1.1
> User-Agent: curl/7.37.1
> Host: gnupg.org
> Accept: */*

Alguma idéia de como obter as informações completas do certificado em uma ferramenta de linha de comando (cURL ou outra)?

Adam Matan
fonte
1
Veja também stackoverflow.com/questions/7885785/…
Vadzim 8/17
Provavelmente depende da versão também. Meu curlsinalizador atual --verbosemostra o conteúdo completo do certificado do servidor.
Patrick Mevzek

Respostas:

263

Você deve poder usar o OpenSSL para sua finalidade:

echo | openssl s_client -showcerts -servername gnupg.org -connect gnupg.org:443 2>/dev/null | openssl x509 -inform pem -noout -text

Esse comando se conecta ao site desejado e canaliza o certificado no formato PEM para outro comando openssl que lê e analisa os detalhes.

(Observe que o -servernameparâmetro "redundante" é necessário para opensslfazer uma solicitação com o suporte SNI.)

Pedro Perez
fonte
Parece haver um erro com este comando:OpenSSL> openssl:Error: 'CONNECTED(00000003)' is an invalid command.
Adam Matan 23/01
2
@AdamMatan Você incluiu o comando completo após o segundo canal? A mensagem de erro parece que a segunda chamada openssl acabou sendo executada no modo interativo (ou seja, opensslvs openssl x509 -inform pem -noout -text). O que Pedro escreveu funciona bem para mim.
Håkan Lindqvist
4
Observe que, enquanto s_client imprimirá toda a cadeia, o último comando canalizado imprimirá apenas informações sobre o primeiro certificado.
chutz
1
echopor si só é equivalente a echo ''.. envia uma string vazia para stdout. cat /dev/null |funcionaria também e é um pouco mais auto-explicativo.
cânhamo
2
Se você quiser apenas saber a data de validade , substitua-a -textpor -enddate, verifique outras opções ( openssl x509 help).
11449 adriaan
63

Solução simples

Esse é o meu roteiro diário:

curl --insecure -v https://www.google.com 2>&1 | awk 'BEGIN { cert=0 } /^\* SSL connection/ { cert=1 } /^\*/ { if (cert) print }'

Resultado:

* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
*    server certificate verification SKIPPED
*    server certificate status verification SKIPPED
*    common name: www.google.com (matched)
*    server certificate expiration date OK
*    server certificate activation date OK
*    certificate public key: RSA
*    certificate version: #3
*    subject: C=US,ST=California,L=Mountain View,O=Google Inc,CN=www.google.com
*    start date: Wed, 24 May 2017 17:39:15 GMT
*    expire date: Wed, 16 Aug 2017 17:13:00 GMT
*    issuer: C=US,O=Google Inc,CN=Google Internet Authority G2
*    compression: NULL
* ALPN, server accepted to use http/1.1
* Connection #0 to host www.google.com left intact
Antonio Feitosa
fonte
5
Não funciona para mim, não inclui as datas de início / validade.
Per Lundberg
4
Como algumas alterações recentes na curvatura (algo entre 49 e 52), isso não mostra nada sobre o certificado. :(
Ross Presser
remova o 2> & 1
Jeshan Babooa
27

Depende do tipo de informação que você deseja, mas:

openssl s_client -showcerts -connect gnupg.org:443

deve lhe dar o máximo, embora não seja tão legível por humanos como o Chrome o apresenta.

falsificador
fonte
1
Infelizmente, muito pouco dos dados do certificado é apresentado em formato legível por humanos por esse comando.
Håkan Lindqvist
9
Discordo do comentário anterior, este comando me diz o que preciso saber e é muito útil. +1 para resposta.
Camdixon
Se você quer especificamente para testar a TLS 1.2 você pode adicionar -tls1_2
camdixon
23
nmap -p 443 --script ssl-cert gnupg.org

Os -p 443especifica para digitalizar apenas a porta 443. Todas as portas serão verificadas se omitidas, e os detalhes do certificado para qualquer serviço SSL encontrado serão exibidos. O comando--script ssl-cert diz ao mecanismo de script do Nmap para executar apenas o ssl-certscript. No documento, esse script "(r) recupera o certificado SSL de um servidor. A quantidade de informações impressas sobre o certificado depende do nível de verbosidade".

Saída de amostra:

Starting Nmap 7.40 ( https://nmap.org ) at 2017-11-01 13:35 PDT
Nmap scan report for gnupg.org (217.69.76.60)
Host is up (0.16s latency).
Other addresses for gnupg.org (not scanned): (null)
rDNS record for 217.69.76.60: www.gnupg.org
PORT    STATE SERVICE
443/tcp open  https
| ssl-cert: Subject: commonName=gnupg.org
| Subject Alternative Name: DNS:gnupg.org, DNS:www.gnupg.org
| Issuer: commonName=Gandi Standard SSL CA 2/organizationName=Gandi/stateOrProvinceName=Paris/countryName=FR
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2015-12-21T00:00:00
| Not valid after:  2018-03-19T23:59:59
| MD5:   c3a7 e0ed 388f 87cb ec7f fd3e 71f2 1c3e
|_SHA-1: 5196 ecf5 7aed 139f a511 735b bfb5 7534 df63 41ba

Nmap done: 1 IP address (1 host up) scanned in 2.31 seconds
Jose Quinteiro
fonte
6

Para verificar os detalhes do certificado SSL, eu uso a seguinte ferramenta de linha de comando desde que ela se tornou disponível:

https://github.com/azet/tls_tools

É ótimo verificar se você tem todas as informações corretas para reemitir certificados ou validar os existentes, além de poucas dependências E não requer configuração.

É assim que as primeiras linhas da saída se parecem:

$ ./check_certificate_chain.py gnupg.org 443

>> Certificate Chain:

 [+]*       OU=Domain Control Validated, OU=Gandi Standard SSL, CN=gnupg.org
 [+]**      C=FR, O=GANDI SAS, CN=Gandi Standard SSL CA
 [+]***     C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware

>> Certificate Information:

................................................................................
- [Subject]:        OU=Domain Control Validated, OU=Gandi Standard SSL, CN=gnupg.org
- [Issuer]:     C=FR, O=GANDI SAS, CN=Gandi Standard SSL CA
- [Valid from]:     Mar 18 00:00:00 2014 GMT
- [Valid until]:    Mar 18 23:59:59 2016 GMT
- [Authority]:      Is not a CA
- [Version]:        2
- [Serial No.]:     43845251655098616578492338727643475746
- [X.509 Extension Details]:
  -- [x509_authorityKeyIdentifier]:
       keyid:B6:A8:FF:A2:A8:2F:D0:A6:CD:4B:B1:68:F3:E7:50:10:31:A7:79:21 

Essa saída é seguida por toda a cadeia de certificados no mesmo nível de detalhe.

O que eu gosto disso, em vez de ser uma ferramenta CLI centrada em ssl, como o s_client do openssl, este tenta fazer apenas o trabalho que precisamos na maioria das vezes. É claro que o openssl é mais flexível (ou seja, também checando clientes, imaps em portas estranhas, etc.) - mas nem sempre preciso disso.

Como alternativa, se você tiver tempo para pesquisar e configurar ou apreciar mais recursos, há a ferramenta maior chamada sslyze (não a utiliza desde dependências e instalação ...)

Florian Heigl
fonte
5

Para completar: se você instalou no seu sistema Java 7 ou superior

 keytool -printcert -sslserver $host[:$port]

mostra a cadeia (como exibida ) com quase todos os detalhes em um formato geralmente bastante feio.

Se você deve ter o Java instalado no seu sistema, eu não respondo.

dave_thompson_085
fonte
saída padrão brilhante e muito mais útil que o openssl (que precisa ser decodificado).
simon
4

Eu uso um script de shell para isso. É apenas um invólucro em torno do comando openssl que me impede de lembrar a sintaxe.

Ele fornece opções para analisar a maioria das informações de certificado em que normalmente estou interessado ou exibir a saída bruta do openssl.

Pode consultar um arquivo de certificado local ou um servidor remoto.

Uso:

$ ssl-cert-info --help
Usage: ssl-cert-info [options]

This shell script is a simple wrapper around the openssl binary. It uses
s_client to get certificate information from remote hosts, or x509 for local
certificate files. It can parse out some of the openssl output or just dump all
of it as text.

Options:

  --all-info   Print all output, including boring things like Modulus and 
               Exponent.

  --alt        Print Subject Alternative Names. These will be typically be 
               additional hostnames that the certificate is valid for.

  --cn         Print commonName from Subject. This is typically the host for 
               which the certificate was issued.

  --debug      Print additional info that might be helpful when debugging this
               script.

  --end        Print certificate expiration date. For additional functionality
               related to certificate expiration, take a look at this script:
               "http://prefetch.net/code/ssl-cert-check".

  --dates      Print start and end dates of when the certificate is valid.

  --file       Use a local certificate file for input.

  --help       Print this help message.

  --host       Fetch the certificate from this remote host.

  --issuer     Print the certificate issuer.

  --most-info  Print almost everything. Skip boring things like Modulus and
               Exponent.

  --option     Pass any openssl option through to openssl to get its raw
               output.

  --port       Use this port when conneting to remote host. If ommitted, port
               defaults to 443.

  --subject    Print the certificate Subject -- typically address and org name.

Examples:

  1. Print a list of all hostnames that the certificate used by amazon.com 
     is valid for.

     ssl-cert-info --host amazon.com --alt
     DNS:uedata.amazon.com
     DNS:amazon.com
     DNS:amzn.com
     DNS:www.amzn.com
     DNS:www.amazon.com

  2. Print issuer of certificate used by smtp.gmail.com. Fetch certficate info
     over port 465.

     ssl-cert-info --host smtp.gmail.com --port 465 --issuer
     issuer= 
         countryName               = US
         organizationName          = Google Inc
         commonName                = Google Internet Authority G2

  3. Print valid dates for the certificate, using a local file as the source of 
     certificate data. Dates are formatted using the date command and display
     time in your local timezone instead of GMT.

     ssl-cert-info --file /path/to/file.crt --dates
     valid from: 2014-02-04 16:00:00 PST
     valid till: 2017-02-04 15:59:59 PST


  4. Print certificate serial number. This script doesn't have a special option
     to parse out the serial number, so will use the generic --option flag to
     pass '-serial' through to openssl.

     ssl-cert-info --host gmail.com --option -serial
     serial=4BF004B4DDC9C2F8

Você pode obter o script aqui: http://giantdorks.org/alain/shell-script-to-check-ssl-certificate-info-like-expiration-date-and-subject/

Alain Kelder
fonte
O link está morto.
Adam Matan
4

Se você quiser fazer isso no Windows, poderá usar o PowerShell com a seguinte função:

function Retrieve-ServerCertFromSocket ($hostname, $port=443, $SNIHeader, [switch]$FailWithoutTrust)
{
    if (!$SNIHeader) {
        $SNIHeader = $hostname
    }

    $cert = $null
    try {
        $tcpclient = new-object System.Net.Sockets.tcpclient
        $tcpclient.Connect($hostname,$port)

        #Authenticate with SSL
        if (!$FailWithoutTrust) {
            $sslstream = new-object System.Net.Security.SslStream -ArgumentList $tcpclient.GetStream(),$false, {$true}
        } else {
            $sslstream = new-object System.Net.Security.SslStream -ArgumentList $tcpclient.GetStream(),$false
        }

        $sslstream.AuthenticateAsClient($SNIHeader)
        $cert =  [System.Security.Cryptography.X509Certificates.X509Certificate2]($sslstream.remotecertificate)

     } catch {
        throw "Failed to retrieve remote certificate from $hostname`:$port because $_"
     } finally {
        #cleanup
        if ($sslStream) {$sslstream.close()}
        if ($tcpclient) {$tcpclient.close()}        
     }    
    return $cert
}

Isso permite que você faça algumas coisas legais, como

#Save to file and open 
Retrieve-ServerCertFromSocket www.wrish.com 443 | Export-Certificate -FilePath C:\temp\test.cer ; start c:\temp\test.cer

#Display the cert details
Retrieve-ServerCertFromSocket www.wrish.com 443 | fl subject,*not*,Thumb*,ser*
Neossian
fonte
2
nmap -sV -sC google.com -p 443
Sergio Rua
fonte
3
Isso precisa de muito mais explicações.
Sven
concordo com a necessidade de explicação, mas funciona para mim, então +1
Jeff
2

Se você deseja apenas a data de validade (que não é exatamente a resposta, mas é 9/10 para a qual as pessoas usam os detalhes do certificado do Chrome), você pode usar:

echo | openssl s_client -connect google.com:443 2>/dev/null | openssl x509 -noout -enddate

Útil para scripts etc.

c4urself@eos ~ → which ssl_expiry
ssl_expiry () {
  echo | openssl s_client -connect ${1}:443 2> /dev/null | openssl x509 -noout -enddate
}
c4urself@eos ~ → ssl_expiry google.com
notAfter=Jun 12 16:54:00 2018 GMT
c4urself
fonte