Obtenga la huella digital de la clave del servidor SSH

83

¿Hay alguna manera de obtener mediante programación una huella digital de la clave del servidor SSH sin autenticarla ?

Estoy intentando ssh -v user@host false 2>&1 | grep "Server host key", pero esto se cuelga esperando una contraseña si la autenticación basada en clave no está configurada.

goncalopp
fuente

Respuestas:

71

Puede hacer esto combinando ssh-keyscany ssh-keygen:

$ file=$(mktemp)
$ ssh-keyscan host > $file 2> /dev/null
$ ssh-keygen -l -f $file
521 de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef host (ECDSA)
4096 8b:ad:f0:0d:8b:ad:f0:0d:8b:ad:f0:0d:8b:ad:f0:0d host (RSA)
$ rm $file

(desafortunadamente lo mucho más simple ssh-keyscan host | ssh-keygen -l -f /dev/stdinno funciona)

Andreas Wiese
fuente
1
¿Tal vez ssh-keygen -l -f - <(ssh-keyscan host)sí?
un CVn
21
OpenSSH> = 7.2 ssh-keyscan puede leer desde stdin:ssh-keyscan host | ssh-keygen -lf -
mykhal
1
Sólo hacer:ssh-keygen -l -f <(ssh-keyscan host)
Christopher
1
Esa es una expresión bastante mala para los scripts de shell, ya que depende de un shell que lo soporte, que POSIX shell no.
Andreas Wiese
2
ssh-keygen -l -f -funciona mucho como se esperaba en ssh-keygen 7.2 y superior. Produce algunas líneas de comentarios a STDERR que se pueden filtrar, como se menciona en la respuesta de Anthony Geoghegan ossh-keyscan host 2>/dev/null | ssh-keygen -l -f -
Cedric Knight el
56

Recientemente tuve que hacer esto yo mismo, así que pensé en agregar una respuesta que muestre cómo se puede hacer esto (con versiones de OpenSSH 7.2 o más recientes ) en una línea usando la sustitución del proceso:

ssh-keygen -lf <(ssh-keyscan hostname 2>/dev/null)

El siguiente texto explica cómo funcionan estos comandos y resalta algunas de las diferencias de comportamiento entre las versiones anteriores y nuevas de las utilidades OpenSSH.

Obtener claves de host públicas

El ssh-keyscancomando se desarrolló para que los usuarios puedan obtener claves de host públicas sin necesidad de autenticarse en el servidor SSH. Desde su página de manual:

ssh-keyscanes una utilidad para recopilar las claves de host ssh públicas de varios hosts. Fue diseñado para ayudar en la construcción y verificación de ssh_known_hostsarchivos.

Tipo de llave

El tipo de clave que se va a buscar se especifica mediante la -topción

  • rsa1 (Protocolo SSH obsoleto versión 1)
  • rsa
  • dsa
  • ecdsa (versiones recientes de OpenSSH)
  • ed25519 (versiones recientes de OpenSSH)

En las versiones modernas de OpenSSH, los tipos de clave predeterminados a buscar son rsa (desde la versión 5.1), ecdsa(desde la versión 6.0) y ed25519(desde la versión 6.7).

Con versiones anteriores de ssh-keyscan(antes de OpenSSH versión 5.1), el tipo de clave predeterminado era el obsoleto rsa1(Protocolo SSH 1), por lo que los tipos de clave deberían especificarse explícitamente:

ssh-keyscan -t rsa,dsa hostname

Obtenga hashes de huellas dactilares de claves Base64

ssh-keyscanimprime la clave de host del servidor SSH en formato codificado en Base64 . Para convertir esto en un hash de huellas digitales, la ssh-keygenutilidad se puede usar con su -lopción para imprimir la huella digital de la clave pública especificada.

Si usa Bash, Zsh (o el shell Korn), la sustitución del proceso se puede usar para una práctica línea:

ssh-keygen -lf <(ssh-keyscan hostname 2>/dev/null)

Nota : Con las versiones de OpenSSH anteriores a 7.2, las funciones utilizadas ssh-keygenpara leer archivos no manejaban las canalizaciones con nombre (FIFO) muy bien, por lo que este método no funcionaría, por lo que se requiere el uso de archivos temporales.

Algoritmos de hash

Versiones recientes de huellas dactilares de ssh-keygenimpresión SHA256 de las teclas. Para obtener los valores hash MD5 de las huellas digitales de la clave del servidor (el comportamiento anterior), la -E opción se puede usar para especificar el algoritmo hash:

ssh-keygen -E md5 -lf <(ssh-keyscan hostname 2>/dev/null)

Usando una tubería

Si usa un shell POSIX (como dash) que no presenta sustitución de proceso, las otras soluciones que usan archivos temporales funcionarán. Sin embargo, con las versiones más nuevas de OpenSSH (desde 7.2), se puede usar una tubería simple ya ssh-keygenque aceptará -como un nombre de archivo para la secuencia de entrada estándar, lo que permite un comando de tubería de una línea.

ssh-keyscan hostname 2>/dev/null | ssh-keygen -E md5 -lf -
Anthony G - justicia para Monica
fuente
Respuesta agradable y completa, ¡esto es ciertamente mejor que tener un archivo temporal! ¿Puedo sugerirle que proporcione un TL; DR al principio con la versión de sustitución del proceso, para que las personas impacientes lo encuentren más rápido? :)
goncalopp
3
No parece funcionar en Ubuntu 14.04 LTS; Me sale un error "/ dev / fd / 63 no es un archivo de clave pública". El subproceso funciona.
Melle
@melleb Encontré lo mismo en un sistema 12.04 al que tengo acceso. Sospecho que ssh-keygenlas versiones anteriores de OpenSSH tienen un problema al leer desde la tubería FIFO / con nombre. Investigaré esto (y actualizaré mi respuesta) cuando tenga algo de tiempo libre.
Anthony G - justicia para Monica
3
@melleb Después de pasar mi tiempo de descarga descargando varias versiones de código fuente e insertando printfdeclaraciones de depuración en la do_fingerprint()función, descubrí que con las versiones de OpenSSH anteriores a 7.2, las funciones utilizadas ssh-keygenpara leer archivos no manejaban muy bien las canalizaciones con nombre (FIFOs) el método de sustitución del proceso no funcionaría.
Anthony G - justicia para Monica
Esto funciona, pero si lo usa para verificar una huella digital, los usuarios deben saber que existe una condición de carrera: la huella digital que está verificando con este comando no es necesariamente la de la clave que obtiene, a menos que la descargue antes de llamar a ssh- keygen en él.
CodeGnome
20

nmapproporciona esta habilidad usando el ssh-hostkeyscript.

Para devolver la huella digital hexadecimal de la clave:

$ nmap [SERVER] --script ssh-hostkey

Para devolver el contenido de la clave:

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey=full

Para devolver la burbuja visual de la clave

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey='visual bubble'

Para devolver todo lo anterior:

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey=all

Fuente: nmap docs

Arroyo
fuente
3
¿Asumen estos ejemplos que SSH siempre se ejecuta en el puerto 22? ¿Qué pasa si ssh escucha en un puerto no estándar?
Martin Vegter
3
@MartinVegter (parafraseando a Guarin42, que no pudo comentar :) nmap tiene la -popción de especificar un puerto, por ejemplo -p 22000. También es posible usar la -vvopción para aumentar la verbosidad (cantidad de información dada)
goncalopp
2

Filezilla muestra claves hash con md5 en formato hexadecimal .

para encontrar esto en su máquina ubuntu linux use este comando:

ssh-keygen -l -E md5 -f <(ssh-keyscan localhost 2>/dev/null)

nota: reemplace "localhost" con la ip de la máquina que desea verificar.

Cameron
fuente
1

Aquí hay un script de shell (principalmente Bourne shell pero usando una localpalabra clave, que está disponible en la mayoría de los modernos /bin/sh) que he escrito para hacer esto. Úselo como ssh-hostkey hostname. Mostrará las huellas dactilares en formato sha256 y md5 para todas las teclas de host para el nombre de host o la dirección IP dados. También puede especificar manualmente " md5" o " sha256" como el segundo argumento para mostrar solo ese formato en particular.

Utiliza un archivo temporal en lugar de tuberías para que sea compatible con paquetes OpenSSH más antiguos (como se describe en otras respuestas). El archivo temporal usa /dev/shm(memoria compartida) si está disponible.

#!/bin/sh
usage () {
  printf '%s\n' "Usage: ssh-hostkey HOSTNAME [FPRINTHASH]"
}

ssh_hostkey () {
  local host="$1"
  local fprinthash="$2"
  local tmp=

  case "$host" in
    -h|--help|'')
      usage >&2
      return 1
      ;;
  esac

  case "$fprinthash" in
    md5|sha256|'') true;;
    *)
      usage >&2
      printf '%s\n' "Fingerprint hash may be 'md5' or 'sha256'" >&2
      return 2
      ;;
  esac

  if test -d /dev/shm
  then tmp="$(mktemp -d -p /dev/shm)"
  else tmp="$(mktemp -d)"
  fi

  trap 'trap - INT TERM EXIT; rm -rf "$tmp"' INT TERM EXIT
  ssh-keyscan "$host" > "$tmp/f" 2> /dev/null
  case "$fprinthash" in
    sha256|'') ssh-keygen -l -f "$tmp/f" 2> /dev/null;;
  esac
  case "$fprinthash" in
    md5|'') ssh-keygen -l -E md5 -f "$tmp/f" 2> /dev/null;;
  esac

  trap - INT TERM EXIT
  rm -rf "$tmp" > /dev/null 2>&1
}

ssh_hostkey "$@"
ejm
fuente