¿Cómo descargar el certificado SSL de un sitio web?

Respuestas:

246

Para descargar el certificado, debe utilizar el cliente integrado en openssl de la siguiente manera:

echo -n | openssl s_client -connect HOST:PORTNUMBER \
    | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/$SERVERNAME.cert

Eso guardará el certificado en /tmp/$SERVERNAME.cert.

Puede usarlo -showcertssi desea descargar todos los certificados de la cadena. Pero si solo desea descargar el certificado del servidor, no es necesario especificar-showcerts

echo -n da una respuesta al servidor, para que se libere la conexión

sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'elimina información sobre la cadena de certificados y los detalles de conexión. Este es el formato preferido para importar el certificado a otros almacenes de claves.

Sean Reifschneider
fuente
99
Aprecio que no solo hayas dado una buena respuesta, sino también una explicación precisa.
marco.m
¿ -showcertsMuestra también el servidor / certificado de hoja? Pensé que solo mostraba intermedios cuando se incluía ese interruptor.
Mike B
Como decía la respuesta, s_clientsiempre muestra el certificado del servidor (si hay uno, es decir, el servidor responde a hola y no elige un conjunto anónimo). -showcertsmuestra todos los certificados recibidos, primero el certificado del servidor y luego los intermedios y / o la raíz.
dave_thompson_085
44
Sin embargo, esto no funciona en presencia de un proxy.
Frederick Nord
2
Esto tampoco funciona con servidores que usan SNI (múltiples certificados / dominios en una sola dirección IP). Para evitar problemas, especifique el parámetro del nombre del servidor de openssl: openssl s_client -connect HOST: PORTNUMBER -servername CN
verhage
60

Encontré la respuesta. Openssl lo proporciona.

openssl s_client -connect $ {REMHOST}: $ {REMPORT}

RainDoctor
fuente
2
también openssl x509 -text <<EOF cert-text EOFpara ver detalles del certificado
mpapis
2
sudo rm -f cert.pem && sudo echo -n | openssl s_client -connect localhost:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ./cert.pemcortesía de serverfault.com/questions/139728/…
pulkitsinghal
esto logra lo mismo y se salta el sedtruco.
phs
Esto solo verifica un certificado, ¿qué sucede si el servicio es parte de un grupo de servidores con equilibrio de carga, cada uno de los cuales tiene un certificado diferente, posiblemente firmado por una CA raíz diferente? O, en otras palabras, un ataque mitm podría permitir que esta solicitud ingrese al sitio real y luego dirigir otras solicitudes a sus servidores. ¿Hay alguna forma de verificar esto? ¿Y para obtener una lista de todos los certificados que realmente tiene un dominio?
Jens Timmerman
@JensTimmerman "O, en otras palabras, un ataque mitm podría permitir que esta solicitud llegue al sitio real y luego dirigir otras solicitudes a sus servidores". Eso no es posible a menos que el intermediario tenga un certificado válido para el servidor de destino (o el cliente sea tonto, no verifica el certificado del servidor). Evidentemente, si el servidor a veces ofrece un certificado diferente, solo puede esperar obtenerlos eventualmente repitiendo los intentos de conexión.
David Tonhofer
22

La herramienta de cliente GNUTLSgnutls-cli también puede facilitar esto:

gnutls-cli --print-cert www.example.com \
        < /dev/null \
        > www.example.com.certs

El programa está diseñado para proporcionar un cliente interactivo al sitio, por lo que debe proporcionarle una entrada vacía (en este ejemplo, desde /dev/null) para finalizar la sesión interactiva.

nariz grande
fuente
1
¿Cómo haría que gnutls se conectara a través del proxy https (el sistema configurado) e imprimiera el certificado que intercambia?
Frederick Nord
9

basado en la respuesta @bignose, aquí hay una versión independiente que encaja bien, por ejemplo, en una receta de chef:

sudo apt-get install gnutls-bin 
gnutls-cli --print-cert myserver.com </dev/null| sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > myserver.crt
sudo cp myserver.crt /usr/local/share/ca-certificates/myserver.crt
sudo update-ca-certificates
oDDsKooL
fuente
6
true | openssl s_client -connect google.com:443 2>/dev/null | openssl x509

este modo de openssl espera stdin, por lo que lo proporcionamos a través de true |, esto se conecta al servidor especificado en el parámetro -connect. 2>/dev/nullsilencia los errores (opcional), podemos pasar toda la salida al analizador x509, especificando el /dev/stdinuso de la tubería de shell como el archivo de entrada. Y que es la salida sólo el -----BEGIN CERTIFICATE-----que -----END CERTIFICATE-----parte de la s_clientsalida. Puede redirigir eso a un archivo agregando > google.com.pemal final del comando.


Lo mejor que puedo decir es que esto no verifica la cadena de certificados, solo puede decirle qué identidad SSL proporciona el servidor final.

ThorSummoner
fuente
2
(1) esto realmente no mejora las respuestas de hace 6 años (2) x509lee stdin por defecto, por lo que -in /dev/stdines redundante (3) s_clientverifica que el certificado del servidor se encadene correctamente a un ancla de confianza local (root) y no haya expirado, pero suprimió la información que mostraría esto (4) NO verifica la revocación (5) verifica el nombre en el certificado del servidor solo en 1.0.2 y luego no de manera predeterminada (pero puede verificarlo usted mismo fácilmente mirando el certificado después)
dave_thompson_085
@ dave_thompson_085, la pregunta es cómo descargar el certificado, pero no mostrar la información de la cadena. Me gusta el openssl x509 mucho mejor que sed en otra respuesta.
Der_Meister
0

Sintaxis alternativa usando Ex y sustitución de procesos:

ex +'/BEGIN CERTIFICATE/,/END CERTIFICATE/p' <(echo | openssl s_client -showcerts -connect example.com:443) -scq > file.crt
kenorb
fuente