SSH apretón de manos en palabras simples.

Secure Shell (SSH) es un protocolo de capa de transporte ampliamente utilizado para proteger las conexiones entre clientes y servidores. Este es el protocolo básico en nuestro programa Teleport para acceso seguro a la infraestructura. A continuación se muestra una descripción relativamente breve del protocolo de enlace que se produce antes de establecer un canal seguro entre el cliente y el servidor y antes de comenzar el cifrado completo del tráfico.

Compartir versiones


El apretón de manos comienza con el hecho de que ambas partes se envían una cadena con el número de versión. No sucede nada extremadamente emocionante en esta parte del apretón de manos, pero debe tenerse en cuenta que la mayoría de los clientes y servidores relativamente modernos solo admiten SSH 2.0 debido a fallas de diseño en la versión 1.0.

Intercambio de claves


Durante el proceso de intercambio de claves (a veces llamado KEX), las partes intercambian información disponible públicamente y obtienen un secreto compartido por el cliente y el servidor. Este secreto no puede ser descubierto u obtenido de la información disponible públicamente.

Inicialización de intercambio de claves


El intercambio de claves comienza con el hecho de que ambas partes se envían entre sí un mensaje SSH_MSG_KEX_INIT con una lista de primitivas criptográficas compatibles y su orden preferido.

Las primitivas criptográficas deben establecer los bloques de construcción que se utilizarán para el intercambio de claves y luego el cifrado de datos completo. La siguiente tabla enumera las primitivas criptográficas que admite Teleport.

Intercambio de claves (KEX)Cifrado simétricoCódigo de autenticación de mensaje (MAC)Algoritmo de clave de host del servidor
curve25519-sha256@libssh.orgchacha20-poly1305@openssh.comhmac-sha2-256-etm@openssh.comssh-rsa-cert-v01@openssh.com
ecdh-sha2-nistp256aes128-gcm@openssh.comhmac-sha2-256ssh-rsa
ecdh-sha2-nistp384aes256-ctr
ecdh-sha2-nistp521aes192-ctr
aes128-ctr
Teleportar primitivas criptográficas predeterminadas

Inicialización del protocolo Diffie-Hellman en curvas elípticas


Dado que ambas partes usan el mismo algoritmo para seleccionar primitivas criptográficas de la lista de compatibles, después de la inicialización, puede comenzar a intercambiar claves de inmediato. Teleport solo admite el protocolo Elliptic Curve Diffie-Hellman (ECDH), por lo que el intercambio de claves comienza con el cliente que genera un par de claves efímeras (clave pública privada y asociada) y envía al servidor su clave pública en el mensaje SSH_MSG_KEX_ECDH_INIT .

Vale la pena enfatizar que este par de claves es efímero: se usa solo para el intercambio de claves y luego se eliminará. Esto hace que sea extremadamente difícil llevar a cabo una clase de ataques en los que un atacante registra pasivamente el tráfico cifrado con la esperanza de robar la clave privada en algún momento en el futuro (como lo establece la ley de Yarovaya, aprox. Trans.). Es muy difícil robar algo que ya no existe. Esta propiedad se llama secretismo directo.

Fig. 1. Generando un mensaje de inicialización de intercambio de claves

Respuesta de Diffie-Hellman en curvas elípticas


El servidor espera el mensaje SSH_MSG_KEX_ECDH_INIT , y al recibirlo genera su propio par de claves efímeras. Usando la clave pública del cliente y su propio par de claves, el servidor puede generar un secreto compartido K.

Luego, el servidor genera algo llamado el hash de intercambio H y lo firma, generando un hash HS firmado (más en la Fig. 3). El hash de intercambio y su firma tienen varios propósitos:

  • Dado que el hash de intercambio incluye un secreto compartido, demuestra que la otra parte pudo crear un secreto compartido.
  • El ciclo de hash / verificación de la firma de hash e intercambio permite al cliente verificar que el servidor posee la clave privada del host y, por lo tanto, el cliente está conectado al servidor correcto (si el cliente puede confiar en la clave pública correspondiente, más sobre esto más adelante).
  • Al firmar el hash en lugar de firmar los datos de entrada, el tamaño de los datos que se firman se reduce significativamente y conduce a un apretón de manos más rápido.

El hash de intercambio se genera tomando el hash (SHA256, SHA384 o SHA512, según el algoritmo de intercambio de claves) de los siguientes campos:

  • Magia M Versión del cliente, versión del servidor, mensaje del cliente SSH_MSG_KEXINIT , mensaje del servidor SSH_MSG_KEXINIT .
  • La clave pública (o certificado) del HPub servidor HPub . Este valor (y su correspondiente clave privada HPriv) generalmente se genera durante la inicialización del proceso, y no para cada protocolo de enlace.
  • Clave pública del cliente
  • Clave pública del servidor B
  • Secreto compartido K

Con esta información, el servidor puede construir el mensaje SSH_MSG_KEX_ECDH_REPLY utilizando la clave pública efímera del servidor B , la clave pública del HPub servidor HPub y la firma en el hash de intercambio de HS . Ver fig. 4 para más detalles.


Fig. 2. Generación del intercambio hash H

Tan pronto como el cliente recibió SSH_MSG_KEX_ECDH_REPLY del servidor, tiene todo lo necesario para calcular el secreto K y el hash de intercambio H

En la última parte del intercambio de claves, el cliente recupera la clave pública del host (o certificado) de SSH_MSG_KEX_ECDH_REPLY y verifica la firma del hash de intercambio del HS confirma la propiedad de la clave privada del host. Para evitar ataques del tipo "hombre en el medio" (MitM), después de verificar la firma, la clave pública (o certificado) del host se compara con la base de datos local de hosts conocidos; Si esta clave (o certificado) no es confiable, la conexión se desconecta.

  No se puede establecer la autenticidad del host 10.10.10.10 (10.10.10.10) '.
 La huella digital clave de ECDSA es SHA256: pnPn3SxExHtVGNdzbV0cRzUrtNhqZv + Pwdq / qGQPZO3.
 ¿Estás seguro de que deseas continuar conectando (sí / no)? 
El cliente SSH ofrece agregar la clave de host a la base de datos local de hosts conocidos. Para OpenSSH, esto suele ser ~/.ssh/known_hosts

Tal mensaje significa que la clave presentada no está en su base de datos local de hosts conocidos. Una buena manera de evitar tales mensajes es usar certificados SSH (que Teleport hace de manera predeterminada) en lugar de claves, lo que le permite simplemente almacenar el certificado de la autoridad de certificación en una base de datos local de hosts conocidos y luego verificar todos los hosts firmados por esta CA.


Fig. 3. Generando una respuesta de intercambio de claves ECDH

Nuevas llaves


Antes de comenzar el cifrado de datos en masa, quedaba la última advertencia. Ambas partes deben crear seis claves: dos para el cifrado, dos vectores de inicialización (IV) y dos para la integridad. Usted puede preguntar, ¿por qué hay tantas llaves adicionales? ¿No es K lo suficientemente secreto? No, no lo suficiente

Primero, ¿por qué necesitamos claves separadas para encriptación, integridad y IV? Una razón está relacionada con el desarrollo histórico de protocolos como TLS y SSH, a saber, la negociación de primitivas criptográficas. En algunas primitivas criptográficas seleccionadas, la reutilización de claves no es un problema. Pero, como Henryk Hellstrom explica correctamente, si las primitivas se seleccionan incorrectamente (por ejemplo, AES-256-CBC para el cifrado y AES-256-CBC-MAC para la autenticación), las consecuencias pueden ser desastrosas. Cabe señalar que los desarrolladores de protocolos están abandonando gradualmente dicha flexibilidad para hacer que los protocolos sean más simples y seguros.

A continuación, ¿por qué se utilizan claves de cada tipo?

Las claves de cifrado garantizan la confidencialidad de los datos y se utilizan con un cifrado simétrico para cifrar y descifrar un mensaje.

Las claves de integridad se usan comúnmente con el Código de autenticación de mensajes (MAC) para garantizar la autenticidad del texto cifrado. En ausencia de verificaciones de integridad, un atacante puede modificar el texto cifrado que se transmite a través de canales abiertos y usted descifrará un mensaje falso. Este esquema generalmente se llama Encrypt-then-MAC .

Cabe señalar que los cifrados AEAD modernos (cifrado autenticado con datos adjuntos, cuando parte del mensaje está cifrado, parte permanece abierta y todo el mensaje está completamente autenticado) como aes128-gcm@openssh.com y chacha20-poly1305@openssh.com realidad no usan la clave derivada integridad para el MAC, y realizar autenticación dentro de su estructura.

Los vectores de inicialización (IV) suelen ser números aleatorios utilizados como entrada para un cifrado simétrico. Su objetivo es garantizar que el mismo mensaje, encriptado dos veces, no conduzca al mismo texto cifrado. La necesidad de tal procedimiento queda perfectamente demostrada por la famosa imagen del pingüino Tux, encriptada en modo de libro de códigos electrónicos (BCE).


De izquierda a derecha. (1) Texto claro como una imagen. (2) Un criptograma obtenido por encriptación en modo ECB. (3) Un criptograma obtenido por encriptación en un modo diferente al BCE. La imagen es una secuencia de píxeles seudoaleatoria

Usar (y piratear) vectores IV es un tema interesante en sí mismo, sobre el cual Filippo Walsord escribió .

Finalmente, ¿por qué las claves vienen en pares? Como señaló Thomas Pornin , si solo se usa una clave de integridad, un atacante puede reproducir el registro que se le envió al cliente, y lo considerará válido. Con las claves de integridad emparejadas (en el servidor y el cliente), el cliente verificará la integridad del texto cifrado y este truco no funcionará.

Ahora, entendiendo por qué se necesitan estas claves, veamos cómo se generan de acuerdo con el RFC :

  • Iniciando el vector IV del cliente al servidor: HASH(K || H || «A» || session_id)
  • Iniciando el vector IV del servidor al cliente: HASH(K || H || «B» || session_id)
  • Clave de cifrado del cliente al servidor: HASH(K || H || «C» || session_id)
  • Clave de cifrado del servidor al cliente: HASH(K || H || «D» || session_id)
  • Clave de control de integridad del cliente al servidor: HASH(K || H || «E» || session_id)
  • Clave de control de integridad del servidor al cliente: HASH(K || H || «F» || session_id)

Aquí se usa el algoritmo hash SHA {256, 384 o 512} dependiendo del algoritmo de intercambio de claves y el símbolo || implica concatenación, es decir, tracción.

Tan pronto como se calculan estos valores, ambas partes envían SSH_MSG_NEWKEYS para informar a la otra parte que el intercambio de claves se ha completado y que todas las comunicaciones futuras deben ocurrir utilizando las nuevas claves creadas anteriormente.


Fig. 4:. Generación inicial de vectores IV. La generación de otras claves ocurre de acuerdo con el mismo esquema, si reemplazamos A y B con C, D, E y F, respectivamente.

Conclusión


En esta etapa, ambas partes acordaron primitivas criptográficas, intercambiaron secretos y generaron material clave para las primitivas seleccionadas. Ahora se puede establecer un canal seguro entre el cliente y el servidor, lo que garantizará la confidencialidad y la integridad.

Así es como los apretones de manos SSH establecen una conexión segura entre clientes y servidores.

Source: https://habr.com/ru/post/474654/


All Articles