viernes, 17 de noviembre de 2023

Que es el fingerprint de un servidor SSH y que utilidad tiene Y Entendiendo (y usando) SSH fingerprint

Está Escrito:

Y el Verbo se hizo carne, y habitó entre nosotros, y vimos su gloria, gloria como del unigénito del Padre, lleno de gracia y de verdad. (Juan 1:14)

Tomado de: geekland

 La primera vez que nos conectamos a un servidor SSH obtenemos mensajes de advertencia sobre el fingerprint similares al siguiente:

The authenticity of host '192.168.1.123 (192.168.1.123)' can't be established.
ECDSA key fingerprint is SHA256:TiqZXJITgH/kUE9WoNP4TF2xkescmKxFIe33TpsQRC7.
Are you sure you want to continue connecting (yes/no)?

Esta advertencia es para prevenir que nos conectemos a un servidor SSH malicioso y evitar ataques man in the middle. En lenguaje llano, la advertencia nos está preguntando si estamos seguros de conectarnos al servidor SSH que tiene el fingerprint SHA256:RiqYXJITgH/kUE9WoNP4TF2xkescmKxFIe33TpsQRC8.

¿QUÉ ES EL FINGERPRINT DE UN SERVIDOR SSH?

En el momento que se generan las claves pública y privada de un servidor SSH, se genera una huella digital única para cada una de estas llaves. Esta huella digital única es el fingerprint y su principal función es identificar de forma inequívoca un servidor.

¿QUÉ UTILIDAD TIENE EL FINGERPRINT DE UN SERVIDOR SSH?

En el momento que nos conectamos al servidor SSH se inicia un proceso autenticación. El proceso es el siguiente:

  1. Cuando el cliente se conecta al servidor consulta el archivo ~/.ssh/known_hosts. El fichero ~/.ssh/known_hosts es una base de datos de fingerprints de los servidores SSH a los que nos hemos conectado.
  2. Si el fingerprint del servidor SSH al que nos conectamos está almacenado en ~/.ssh/known_hosts, querrá decir que no es la primera vez que nos conectamos al servidor. Por lo tanto a priori se trata de un servidor conocido y seguro al que nos podremos conectar sin ningún tipo de problema.
  3. En el caso que el fingerprint del servidor SSH no esté almacenado en nuestro ~/.ssh/known_hosts nos aparecerá el mensaje de advertencia que hemos visto al inicio del artículo. En este caso deberemos proceder según se indica en los puntos 4 y 5.
  4. Si no es la primera vez que nos conectamos al servidor y nos aparece la advertencia tenemos que responder no y abortar la conexión. Si nos encontramos con esta situación pueden estar pasando 2 cosas. La primera de ellas no es peligrosa y es que el administrador del servidor haya generado un par de llaves nuevo. Si este es el caso nos podemos conectar al servidor sin ningún tipo de problema.  La segunda es que estemos recibiendo un ataque del tipo man in the middle, y que el servidor al que nos estamos conectando sea un servidor malicioso que pretende robar nuestras credenciales. Una vez robadas nuestras credenciales el atacante podrá conectarse al servidor real en nombre nuestro. Si este es el caso aborten de inmediato la conexión al servidor.
  5. Si aparece el mensaje de advertencia y es la primera vez que nos conectamos al servidor no nos debemos preocupar. Tan solo tenemos que comprobar que el fingerprint de la advertencia corresponda al fingerprint del servidor SSH. Si el fingerprint es correcto escribiremos yes, presionaremos la tecla Enter y seguidamente nos conectaremos al servidor. En el momento que nos hayamos conectado al servidor, el fingerprint del servidor se almacenará en nuestro archivo ~/.ssh/known_hostsEn el caso que el fingerprint no sea correcto debemos responder no y abortar la conexión de inmediato.

Por lo tanto queda claro que el fingerprint es una mecanismo para asegurar que nos estamos conectado al servidor al que realmente queremos conectarnos.

¿CÓMO PODEMOS SABER EL FINGERPRINT DE NUESTRO SERVIDOR SSH?

Nos dirigimos al directorio donde se almacenan las claves privadas y públicas de nuestro servidor. Para ello ejecutamos el siguiente comando en la terminal:

cd /etc/ssh

Para visualizar nuestras claves privadas ejecutamos el siguiente comando en la terminal:

ls -l

El resultado obtenido en mi caso es el siguiente:

root@debian:/etc/ssh$ ls -ls
total 576
-rw-r–r– 1 root root 553122 ene 3 2017 moduli
-rw-r–r– 1 root root 1723 ene 3 2017 ssh_config
-rw-r–r– 1 root root 2513 may 10 2015 sshd_config
-rw——- 1 root root 668 jul 17 2014 ssh_host_ed25519_key
-rw-r–r– 1 root root 601 jul 17 2014 ssh_host_ed25519_key.pub
-rw——- 1 root root 227 jul 17 2014 ssh_host_ecdsa_key
-rw-r–r– 1 root root 173 jul 17 2014 ssh_host_ecdsa_key.pub
-rw——- 1 root root 1679 jul 17 2014 ssh_host_rsa_key
-rw-r–r– 1 root root 393 jul 17 2014 ssh_host_rsa_key.pub

El fingerprint de cada una de las llaves se almacena en los ficheros que terminan con la extensión .pub.

Si en el inicio del post consultan el mensaje de advertencia que obtengo al conectarme al servidor verán que se está usando la llave ECDSA. Por lo tanto consultaré el fingerprint de la llave ssh_host_ecdsa_key.pub ejecutado el siguiente comando en la terminal:

ssh-keygen -l -f ssh_host_ecdsa_key.pub

Cada una de los términos del comando tiene el siguiente significado:

ssh-keygen: Utilidad que uso para conseguir mi propósito.
-l: Opción que indica a ssh-keygen que muestre el fingerprint.
-f: Opción para poder especificar el nombre de una llave.
ssh_host_ecdsa_key.pub: Nombre de la llave que quiero averiguar el fingerprint.

El resultado obtenido de ejecutar el comando es el siguiente:

root@debian:ssh-keygen -l -f ssh_host_ecdsa_key.pub
SHA256:TiqZXJITgH/kUE9WoNP4TF2xkescmKxFIe33TpsQRC7 root@debian (ECDSA)

El fingerprint mostrado es el mismo que el que aparece en el mensaje de advertencia de conexión al servidor. Por lo tanto nos podemos conectar al servidor sin ningún tipo de temor.

COMO VER LA FINGERPRINT DE LOS SERVIDORES A LOS QUE ME HE CONECTADO

Como hemos dicho anteriormente, el archivo ~/.ssh/known_hosts almacena la totalidad de fingerprints de los servidores a los que nos hemos conectado.

Por lo tanto para consultar la totalidad de fingerprints tan solo tenemos que ejecutar el siguiente comando en la terminal:

cat ~/.ssh/known_hosts

Procediendo de la forma que describimos en el artículo conseguiremos obtener mayor seguridad en el momento de conectarnos a servidores SSH.

Tomado de: linuxtotal

Entendiendo (y usando) SSH fingerprint 

Copyright © 2005-2023 LinuxTotal.com.mx
Se concede permiso para copiar, distribuir y/o modificar este documento siempre y cuando se cite al autor y la fuente de linuxtotal.com.mx y según los términos de la GNU Free Documentation License, Versión 1.2 o cualquiera posterior publicada por la Free Software Foundation.

Autor: Sergio González D.  

y asi evitar ataques del tipo 'man in the middle'

ssh es quizás (en mi opinión) la mejor herramienta de comunicación que existe cuando se trata de establecer contacto con un servidor remoto Linux. Al decir remoto, me refiero que puede estar situado en el escritorio de al lado o al otro lado del mundo, en la LAN o en alguna parte de Internet. Claro, el servidor tiene que estar ejecutando el demonio o servicio sshd que normalmente funciona en el puerto 22 (ver el artículo servicios para aprender más sobre como iniciarlo). La ventaja de ssh (Secure SHell, por cierto) es que es seguro, el tráfico entre los equipos es encriptado, estable, robusto, fácil de actualizar y usar, etc. Ha tenido serios bugs como cualquier otro programa pero como buen software open source es rápidamente actualizado en cuestión de horas literalmente, cuando nuevas vulnerabilidades se le conocen, además de que tiene utilerías agregadas como scp y sftp, así como clientes excelentes tanto en Linux y Windows, en fin altamente recomendable su uso en la vida diaria de cualquier administrador o usuario Linux.


¿Si todo es tan maravilloso con ssh?, ¿Entonces cual es el problema?

Muy bien. El escenario es el siguiente para entender bien lo que sucede. El cliente se conecta (por primera vez) digamos desde un equipo Windows con un cliente ssh como puede ser putty (si no usas putty, te estás perdiendo el mejor cliente ssh del mundo) a un servidor Linux y aparece el siguiemte cuadro de diálogo: (algo similar pero en modo de texto aparecería desde una consola de texto):

LinuxTotal.com.mx ssh

- mmmmm, ¿Qué diablos es esto?, No tengo tiempo de leer eso, presionaré Si, bien ya entró.


Esto es lo que el usuario común hará al no comprender realmente lo que sucede entre el cliente y el servidor ssh. Al tratarse de un protocolo de comunicación altamente seguro y con tráfico encriptado de punto a punto, entran en juego algoritmos de encriptación. Cada servidor ssh tiene una huella digital única (fingerprint) generada al momento de la instalación. Este fingerprint identifica al servidor en específico. Traduciendo el diálogo anterior diría lo siguiente:

 La llave del servidor anfitrión no está registrada en el registro. Tu
 no tienes garantía que el servidor es la computadora que tu
 piensas que es.
 La clave fingerprint del servidor es:
 1024 63:d1:48:fc:9f:7e:1e:0d:27:d1:7b:23:75:06:34:a2
 Si tu confias en este host, presiona Si para añadir la clave al
 cache de PuTTY y establecer la conexión.
 Si quieres conectarte solo una vez, sin
 añadir la clave al cache, presiona No.
 Si no confias en este host, presiona Cancelar para abandonar la
 conexión.

¿Comienza a quedar claro?, se nos está advirtiendo que el equipo al que queremos conectarnos puede no ser el nuestro, es decir SE TIENE QUE ESTAR SEGURO QUE AL SERVIDOR LINUX QUE ME ESTOY CONECTANDO ES REALMENTE EL MIO y esto solo se logra conociendo previamente el fingerprint del servidor y tenerlo en la Palm, en una nota, o en un papel en la cartera o en un block de notas de la computadora de la casa u otra ubicación, como sea. Si por razones de trabajo u otras, se requiere acceder a un servidor de producción de forma remota ES SUMAMENTE IMPORTANTE CONOCER EL FINGERPRINT DEL SERVIDOR para estar seguro que no me estén interceptando (en un momento se explica esto, calma).

Ok, si, si, pero ¿Como diablos se cuál es el fingerprint de mi servidor?

Ábrete una terminal en tu servidor Linux y te cambias al directorio de configuración de ssh:

#> cd /etc/ssh
#> ls -l
total 173
drwxr-xr-x    2 root root    344 Feb 18 00:18 .
drwxr-xr-x  107 root root   9088 Feb 17 22:57 ..
-rw-------    1 root root 132839 Jan 27 07:51 moduli
-rw-r--r--    1 root root   2517 Jan 27 07:51 ssh_config
-rw-------    1 root root    668 Oct 20 21:26 ssh_host_dsa_key
-rw-r--r--    1 root root    600 Oct 20 21:26 ssh_host_dsa_key.pub
-rw-------    1 root root    525 Oct 20 21:26 ssh_host_key
-rw-r--r--    1 root root    329 Oct 20 21:26 ssh_host_key.pub
-rw-------    1 root root    887 Oct 20 21:26 ssh_host_rsa_key
-rw-r--r--    1 root root    220 Oct 20 21:26 ssh_host_rsa_key.pub
-rw-r-----    1 root root   3482 Feb 18 00:18 sshd_config

Notarás que existen algunos archivos con terminación .pub, pues esta es la parte pública de las llaves de tu servidor ssh pero en forma de un fingerprint, es decir la llave pública generada por los algoritmos dsa o rsa. Generalmente, por default, ssh guarda su llave pública o fingerprint en este caso en el archivo ssh_host_key.pub, si mostramos su contenido se verá lo siguiente:

#> more ssh_host_key.pub
1024 35 161635971725059974812816613188513865727625643323552121445765023013612487474922451108
80703826701959121218181176403629257123317219888287730368486491009806579706597689031242574789
96617659498748196451487737641156043897343204483595648176422701566886723150233655375182156814
44474810364877205687200614515477060949257 root@linux

No nos dice mucho, pero si usamos la herramienta adecuada de las que vienen junto con ssh, se podrá conocer el fingerprint del servidor en un formato de una cadena de números hexadecimales:

#> ssh-keygen -l -f ssh_host_key.pub
1024 63:d1:48:fc:9f:7e:1e:0d:27:d1:7b:23:75:06:34:a2 ssh_host_key.pub
-l -f

Nótese que es el mismo fingerprint mostrado por el diálogo de PuTTY con lo que ahora si estamos seguros que es nuestro servidor. En este punto queda claro entonces que la línea anterior es la que deberás conocer previamente y apuntarla y/o traerla contigo de alguna manera para cuando te conectes remotamente a tu servidor Linux estés totalmente seguro que es el tuyo.

NOTA: ssh puede usar dos protocolos: versión 1 y versión 2. La versión 1 es totalmente obsoleta y con algunas vulnerabilidades conocidas y por lo tanto es inseguro y no aconsejable su uso, se incluye por compatibilidad, pero hay que usar el 2. Si usas el protocolo 1 entonces tu archivo de llave privada (del lado del servidor solamente) es ssh_host_key (rsa1).
Si usas el protocolo 2 tus archivos de llave privada son ssh_host_rsa_key y ssh_host_dsa_key que se usan indistintamente por parte de ssh, aumentando asi el nivel de complejidad en el encriptado del tráfico.
Para asegurarte que solo uses la versión 2 de ssh incluye o asegúrate de tener la siguiente línea en el archivo de configuración de ssh (/etc/ssh/sshd_config).

Protcol 2

IMPORTANTE: Obsérvese que cuando hice el ejemplo de arriba, a propósito dejé la línea de la variable Protocol como se queda por default en muchas distros y que es la siguiente:

Protcol 1,2

Aceptando ambos protocolos y en primer lugar toma el 1, como se aprecia perfectamente en el ejemplo, al observar que el fingerprint corresponde al archivo de llave privada de la versión 1. Esto es algo inaceptable en un servidor Web o de producción en alguna empresa, asi que chécalo bien si es que eres el responsable d e los sistemas Linux.


¿Y quien es Man in the middle (MiM) o el hombre intermedio?

Ahora te preguntarás, ¿Si ssh es tan seguro, entonces cual es el riesgo, o porque la necedad de tener que conocer los fingerprints de mis servidores Linux?. ssh es seguro y confiable una vez establecida la comunicación entre el cliente y el servidor, pero en la vida real no todo es tan perfecto y existe una técnica de hackeo (¿o será hacking?) llamada Man in the middle -hombre intermedio-, que consiste en que el hacker (hombre intermedio) se coloca entre dos equipos (cliente y servidor) y el también es un servidor ssh pero obviamente con otro fingerprint distinto al servidor ssh genuino. Entonces, una vez montado el ataque, es decir, lograr que el tráfico del cliente dirigido al puerto 22 del servidor real se desvié al puerto 22 del hacker, este "cachará" los paquetes en su servidor ssh y los reenviará al servidor ssh genuino y cuando este responda al cliente pasará de vuelta por el equipo del hacker, pudiendo este con una herramienta como wireshark "observar" el tráfico entre los dos y como se desencripta lo que reciba/manda para poder ser pasado por su propio servidor ssh, entonces conocerá TODO lo que circula entre los dos extremos pero desencriptado.

Se entiende ahora la importancia de no presionar "Si" de primera instancia porque si algún hacker en nuestra empresa, ciberinternet, escuela, universidad, etc. logró lo anterior, entonces cuando nos conectemos al servidor ssh la primera vez VEREMOS SU FINGERPRINT NO EL NUESTRO, y si lo conocemos previamente entonces es obvio que no es nuestro servidor y no deberemos conectarnos y por supuesto avisar inmediatamente de la situación al administrador de sistemas del lugar.

Generalmente los ataques "Man in the middle" se logran realizar cuando en la red hay switches mal configurados o no monitorizados mediante técnicas conocidas como envenenamiento arp (arp poissoning), que en pocas palabras consiste en lograr que el switch canalize o envié todos los paquetes de todos sus puertos al puerto del hacker. Es decir corrompiendo las tablas arp (la relación de la dirección IP-dirección MAC) del switch. Tal vez las siguientes imágenes clarifiquen esto:

LinuxTotal.com.mx sshLinuxTotal.com.mx ssh

La conclusión importante de todo esto es que SSH ES TOTALMENTE SEGURO Y CONFIABLE, EL PROBLEMA ESTÁ EN LA RELATIVA FACILIDAD PARA REALIZAR SUPLANTACIONES TIPO MAN IN THE MIDDLE, QUE NO ES PROBLEMA DE LA APLICACIÓN SSH Y LA INSEGURIDAD PRODUCIDA ES POR PARTE DEL USUARIO QUE NO VERIFICA EL FINGERPRINT QUE SEA VÁLIDO O CONOCIDO POR ÉL.


¿Cómo hago para ver los fingerprints de los servidores ssh que ya he aceptado?

En Linux, en tu cuenta que uses se genera un directorio oculto llamado .ssh dentro de el encontrarás un archivo llamado known_hosts que si ejecutas el programa ssh-agent:

$> ssh-agent -l -f known_hosts

te dará una lista de los fingerprints de los hosts a los que te has conectado, basta con eliminar el renglón del host que quieras o eliminar todo el archivo para que la siguiente vez que te conectes al servidor ssh te pregunte de nuevo que si lo aceptas o no.

En Windows con PuTTY, en el menú de la ventana de la termina que se abre hay una opción "event log" donde se observa los fingerprints del servidor al que estás conectado. Si buscas en el registro de Windows "putty" te da la siguiente llave:

\HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys

Y es donde deja el registro de los fingerprints que has usado, pero no entiendo como los guarda porque deja una cadena muy larga y no se aprecia el fingerprint realmente, aunque si queda claro el servidor del que pertence, basta con que borres la clave del registro correspondiente y te volverá a preguntar la siguiente vez que te conectes.


Quiero cambiar mis archivos de fingerprint de mi servidor por otros ¿Cómo se hace eso?

Es perfectamente posible y hasta recomendable cada cierto tiempo en un servidor expuesto al Internet por ejemplo, cambiar el fingerprint de ssh. Para hacer esto usaremos nuestra ya conocida herramienta ssh-keygen: Veámoslo por pasos para dejarlo bien claro:

1er. Paso
Cambiarse a /etc/ssh, no tiene que ser forzosamente aqui pero por cuestiones de organización (y por que aqui están las llaves originales) dejemos nuestras nuevas llaves aqui.

#> cd /etc/ssh

2do. Paso
Asumimos que solo se trabajará con el protocolo 2, asi que debemos de generar archivos de llaves para los algoritmos dsa y rsa:

#> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): /etc/ssh/mi_llave_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /etc/ssh/mi_llave_rsa.
Your public key has been saved in /etc/ssh/mi_llave_rsa.pub.
The key fingerprint is:
e1:40:bb:57:ae:62:dd:bc:a2:3c:3f:35:63:d2:ab:62 root@linux
#>

Se usa la opción -t para indicar el tipo de algoritmo en este caso rsa, se detiene la ejecucción y pregunta por el nombre del archivo donde se guardará la llave privada, indiqué: /etc/ssh/mi_llave_rsa, hay que indicar la ruta completa. Y después pregunta por una contraseña (passphrase), que cuidado!!!!, NO hay que poner nada. Es una llave privada no expuesta a nadie, y ssh en llaves generadas solo para el uso de archivos del mismo servidor necesita NO tener contraseña.

Repetimos lo mismo pero ahora para generar el archivo con dsa:

#> ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/root/.ssh/id_dsa): /etc/ssh/mi_llave_dsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /etc/ssh/mi_llave_dsa.
Your public key has been saved in /etc/ssh/mi_llave_dsa.pub.
The key fingerprint is:
01:aa:d9:9e:33:f1:ea:50:d4:be:e8:e7:dd:a2:ce:de root@linux
#>

Tenemos ya, entonces, cuatro archivos, dos con las llaves privadas y dos con las llaves públicas, que son las que se exportan al cliente al momento de aceptarse la conexión:

#> ls -l mi_llave*
-rw-------  1 root root 668 Feb 19 00:53 mi_llave_dsa
-rw-r--r--  1 root root 602 Feb 19 00:53 mi_llave_dsa.pub
-rw-------  1 root root 883 Feb 19 00:48 mi_llave_rsa
-rw-r--r--  1 root root 222 Feb 19 00:48 mi_llave_rsa.pub

3er. Paso
Hay que reconfigurar el archivo de configuración de ssh (/etc/sshd/sshd_config) donde agregaremos la variable HostKey dos veces indicando en cada una la ruta y archivos recien creados, veamos el bloque completo de esa parte del archivo de configuración como debe quedar.

# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
#HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/mi_llave_rsa
HostKey /etc/ssh/mi_llave_dsa

Obsérvese que aparecen comentadas con un # los archivos de llaves originales, esto es normal, porque son el default.

4to. Paso
Reiniciar el servidor sshd:

#> service sshd restart

O si no se tiene el comando service:

#> /etc/rc.d/init.d sshd restart        
       
#> /etc/init.d/sshd restart

Listo es todo, ssh recibió una nueva huella digital que lo identifique.

¿Que pasará si nos conectamos de nuevo desde Windows con el cliente PuTTY?, veamos el mensaje tan apremiante que nos manda:LinuxTotal.com.mx ssh

Es muy distinto al del primer ejemplo. Debido a que ya se tiene almacenado en el cache del cliente la llave pública, su fingerprint, y al no concordar en este intento de conexión , ya que el servidor tiene un nuevo fingerprint, nos lo advierte.
ESTO ES PRECISAMENTE O ALGO MUY SIMILAR LO QUE SE VERÍA SI HAY UN ATAQUE MAN IN THE MIDDLE, ya que previamente nos hemos estado conectando siempre a nuestro servidor sin ningún mensaje, y de repente aparece esto y si no se ha cambiado el fingerprint o nadie aviso nada, cuidado habrá que investigar. Esto es a lo que me refería cuando mencionaba mas atrás que ssh es seguro, lo que no es seguro es que alguien se nos ponga en medio y peor aun que no hagamos caso a los mensajes. En el primer párrafo dice:

 La llave del servidor no concuerda con la que PuTTY tiene
 guardada en su registro. Esto significa que o el
 administrador ha cambiado la llave del host, o que te estás
 conectando a otra computadora que pretende
 ser el servidor.

Mas claro ni el agua.
En fin, en este caso se puede perfectamente apreciar que el fingerprint que muestra el diálogo es el mismo que se generó cuando creamos el archivo con tipo rsa:

e1:40:bb:57:ae:62:dd:bc:a2:3c:3f:35:63:d2:ab:62

Asi que con toda seguridad procedemos a presionar Si, sabiendo que SI es nuestro servidor.

Ojalá te sirva esta ayuda y si tienes dudas, comentarios, ampliaciones del documento, etc. son bienvenidas.