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.
Teleportar primitivas criptográficas padrãoInicializaçã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 chavesResposta 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 HAssim 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 ECDHNovas 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óriaUsar (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, respectivamenteConclusã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.