Aperto de mão SSH em palavras simples.

O Secure Shell (SSH) é um protocolo de camada de transporte amplamente usado para proteger conexões entre clientes e servidores. Este é o protocolo básico em nosso programa de teleporte para acesso seguro à infraestrutura. Abaixo está uma descrição relativamente breve do handshake que ocorre antes de estabelecer um canal seguro entre o cliente e o servidor e antes de iniciar a criptografia completa do tráfego.

Compartilhamento de versão


O aperto de mão começa com o fato de os dois lados enviarem um ao outro uma sequência com o número da versão. Nada extremamente emocionante acontece nesta parte do handshake, mas deve-se notar que a maioria dos clientes e servidores relativamente modernos oferece suporte apenas ao SSH 2.0 devido a falhas de design na versão 1.0.

Troca de chaves


Em um processo de troca de chaves (às vezes chamado de KEX), as partes trocam informações publicamente disponíveis e derivam um segredo compartilhado pelo cliente e pelo servidor. Este segredo não pode ser descoberto ou obtido a partir de informações publicamente disponíveis.

Inicialização de troca de chaves


A troca de chaves começa com o fato de que ambas as partes enviam uma mensagem SSH_MSG_KEX_INIT com uma lista de primitivas criptográficas suportadas e sua ordem preferida.

As primitivas criptográficas devem estabelecer os blocos de construção que serão usados ​​para a troca de chaves e, em seguida, a criptografia completa dos dados. A tabela abaixo lista as primitivas criptográficas que o Teleport suporta.

Troca de chaves (KEX)Cifra simétricaCódigo de autenticação de mensagem (MAC)Algoritmo de chave do host do 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 padrão

Inicialização do protocolo Diffie-Hellman sobre curvas elípticas


Como os dois lados usam o mesmo algoritmo para selecionar primitivas criptográficas da lista de suportadas, após a inicialização, é possível iniciar imediatamente a troca de chaves. O teleporte suporta apenas o protocolo Elliptic Curve Diffie-Hellman (ECDH), portanto, a troca de chaves começa com o cliente gerando um par de chaves efêmero (chave pública privada e associada) e enviando ao servidor sua chave pública na mensagem SSH_MSG_KEX_ECDH_INIT .

Vale ressaltar que esse par de chaves é efêmero: é usado apenas para troca de chaves e, em seguida, será excluído. Isso torna extremamente difícil realizar uma classe de ataques em que um invasor registra passivamente o tráfego criptografado com a esperança de roubar a chave privada em algum momento no futuro (como a lei de Yarovaya prevê - aprox. Trans.). É muito difícil roubar algo que não existe mais. Essa propriedade é chamada sigilo direto.

Fig. 1. Gerando uma mensagem de inicialização de troca de chaves

Resposta de Diffie-Hellman nas curvas elípticas


O servidor aguarda a mensagem SSH_MSG_KEX_ECDH_INIT e, após o recebimento, gera seu próprio par de chaves efêmero. Usando a chave pública do cliente e seu próprio par de chaves, o servidor pode gerar um segredo compartilhado K.

Em seguida, o servidor gera algo chamado hash de troca H e o assina, gerando um hash HS assinado (mais na Fig. 3). O hash da troca e sua assinatura servem a vários propósitos:

  • Como o hash de troca inclui um segredo compartilhado, isso prova que a outra parte conseguiu criar um segredo compartilhado.
  • O ciclo de hash / verificação da assinatura de hash e troca permite que o cliente verifique se o servidor possui a chave privada do host e, portanto, o cliente está conectado ao servidor correto (se o cliente puder confiar na chave pública correspondente, mais sobre isso posteriormente).
  • Ao assinar o hash em vez de assinar os dados de entrada, o tamanho dos dados que estão sendo assinados é significativamente reduzido e leva a um handshake mais rápido.

O hash de troca é gerado usando o hash (SHA256, SHA384 ou SHA512, dependendo do algoritmo de troca de chaves) dos seguintes campos:

  • Magic M Versão do cliente, versão do servidor, mensagem do cliente SSH_MSG_KEXINIT , mensagem do servidor SSH_MSG_KEXINIT .
  • A chave pública (ou certificado) do HPub servidor HPub . Esse valor (e sua chave privada correspondente do HPriv) geralmente é gerado durante a inicialização do processo, e não para cada handshake.
  • Chave pública do cliente
  • Chave pública do servidor B
  • Segredo compartilhado K

Com essas informações, o servidor pode construir a mensagem SSH_MSG_KEX_ECDH_REPLY usando a chave pública efêmera do servidor B , a chave pública do host do servidor HPub e a assinatura no hash de troca HS . Veja a fig. 4 para mais detalhes.


Fig. 2. Geração do hash de troca H

Assim que o cliente recebeu SSH_MSG_KEX_ECDH_REPLY do servidor, ele tem todo o necessário para calcular o segredo K e o hash de troca H

Na última parte da troca de chaves, o cliente recupera a chave pública (ou certificado) do host de SSH_MSG_KEX_ECDH_REPLY e verifica a assinatura do hash da troca HS confirmando a propriedade da chave privada do host. Para evitar ataques do tipo "man in the middle" (MitM), após verificar a assinatura, a chave pública (ou certificado) do host é verificada no banco de dados local de hosts conhecidos; se essa chave (ou certificado) não for confiável, a conexão será desconectada.

  A autenticidade do host 10.10.10.10 (10.10.10.10) 'não pode ser estabelecida.
 A impressão digital da chave ECDSA é SHA256: pnPn3SxExHtVGNdzbV0cRzUrtNhqZv + Pwdq / qGQPZO3.
 Tem certeza de que deseja continuar se conectando (sim / não)? 
O cliente SSH oferece adicionar a chave do host ao banco de dados local de hosts conhecidos. Para o OpenSSH, geralmente é ~/.ssh/known_hosts

Essa mensagem significa que a chave apresentada não está no banco de dados local de hosts conhecidos. Uma boa maneira de evitar essas mensagens é usar certificados SSH (o que o Teleport faz por padrão) em vez de chaves, o que permite armazenar o certificado da autoridade de certificação em um banco de dados local de hosts conhecidos e verificar todos os hosts assinados por esta CA.


Fig. 3. Gerando uma resposta de troca de chaves ECDH

Novas chaves


Antes de iniciar a criptografia de dados em massa, a última advertência permaneceu. Ambas as partes devem criar seis chaves: duas para criptografia, dois vetores de inicialização (IV) e duas para integridade. Você pode perguntar, por que existem tantas chaves extras? K não é segredo o suficiente? Não, não é suficiente.

Primeiro, por que precisamos de chaves separadas para criptografia, integridade e IV. Uma razão está relacionada ao desenvolvimento histórico de protocolos como TLS e SSH, a saber, a negociação de primitivas criptográficas. Em algumas primitivas criptográficas selecionadas, a reutilização de chave não é um problema. Mas, como Henryk Hellstrom explica corretamente, se as primitivas forem selecionadas incorretamente (por exemplo, AES-256-CBC para criptografia e AES-256-CBC-MAC para autenticação), as consequências podem ser desastrosas. Deve-se notar que os desenvolvedores de protocolos estão gradualmente abandonando essa flexibilidade para tornar os protocolos mais simples e mais seguros.

Em seguida, por que as chaves de cada tipo são usadas.

As chaves de criptografia garantem a confidencialidade dos dados e são usadas com uma cifra simétrica para criptografar e descriptografar uma mensagem.

As chaves de integridade são comumente usadas com o MAC (Message Authentication Code) para garantir a autenticidade do texto cifrado. Na ausência de verificações de integridade, um invasor pode modificar o texto cifrado transmitido pelos canais abertos e você descriptografará uma mensagem falsa. Esse esquema geralmente é chamado de Criptografar e depois MAC .

Deve-se observar que as cifras AEAD modernas (criptografia autenticada com dados anexados, quando parte da mensagem é criptografada, parte permanece aberta e a mensagem inteira é completamente autenticada) como aes128-gcm@openssh.com e chacha20-poly1305@openssh.com na verdade não usam a chave derivada integridade para o MAC e execute a autenticação dentro de sua estrutura.

Os vetores de inicialização (IV) geralmente são números aleatórios usados ​​como entrada para uma cifra simétrica. Seu objetivo é garantir que a mesma mensagem, criptografada duas vezes, não leve ao mesmo texto cifrado. A necessidade de tal procedimento é perfeitamente demonstrada pela famosa imagem do pingüim Tux, criptografada no modo ECB (Electronic Code Book).


Da esquerda para a direita. (1) Texto nítido como imagem. (2) Um criptograma obtido por criptografia no modo BCE. (3) Um criptograma obtido por criptografia em um modo diferente do BCE. A imagem é uma sequência de pixels pseudo-aleatória

Usar (e invadir) vetores IV é um tópico interessante em si, sobre o qual Filippo Walsord escreveu .

Finalmente, por que as chaves vêm em pares? Como observou Thomas Pornin , se apenas uma chave de integridade for usada, um invasor poderá reproduzir o registro enviado a ele para o cliente, e ele o considerará válido. Com chaves de integridade emparelhadas (no servidor e no cliente), o cliente verificará a integridade do texto cifrado e esse truque não funcionará.

Agora, com a compreensão do porquê dessas chaves serem necessárias, vamos ver como elas são geradas de acordo com a RFC :

  • Iniciando o vetor IV do cliente para o servidor: HASH(K || H || «A» || session_id)
  • Iniciando o vetor IV do servidor para o cliente: HASH(K || H || «B» || session_id)
  • Chave de criptografia do cliente para o servidor: HASH(K || H || «C» || session_id)
  • Chave de criptografia do servidor para o cliente: HASH(K || H || «D» || session_id)
  • Chave de controle de integridade do cliente para o servidor: HASH(K || H || «E» || session_id)
  • Chave de controle de integridade do servidor para o cliente: HASH(K || H || «F» || session_id)

Aqui, o algoritmo de hash SHA é usado {256, 384 ou 512}, dependendo do algoritmo de troca de chaves e do símbolo || implica concatenação, ou seja, tração.

Assim que esses valores são calculados, os dois lados enviam SSH_MSG_NEWKEYS para informar o outro lado que a troca de chaves está concluída e todas as comunicações futuras devem ser feitas usando as novas chaves criadas acima.


Fig. 4:. Geração inicial do vetor IV. A geração de outras chaves ocorre de acordo com o mesmo esquema, se substituirmos A e B por C, D, E e F, respectivamente

Conclusão


Nesse estágio, ambas as partes concordaram em primitivas criptográficas, trocaram segredos e geraram material-chave para as primitivas selecionadas. Agora, um canal seguro pode ser estabelecido entre o cliente e o servidor, o que garantirá confidencialidade e integridade.

É assim que os handshakes SSH estabelecem uma conexão segura entre clientes e servidores.

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


All Articles