O que está escrito no arquivo .ssh / known_hosts


Cada vez que nos conectamos através do protocolo ssh ao servidor, o cliente ssh verifica se a chave pública desse servidor corresponde à última vez (pelo menos recomenda fazer o padrão ssh). No OpenSSH, uma lista de chaves conhecidas do servidor é armazenada no arquivo known_hosts. Sob katom brevemente sobre o que e como exatamente é armazenado lá.

Todos os experimentos foram conduzidos no Linux (Debian / Mint / Ubuntu). Não posso garantir a localização e o conteúdo dos arquivos em outros sistemas operacionais.

Ao conectar-se ao servidor ssh pela primeira vez, vemos algo assim:
A autenticidade do host '192.168.0.2 (192.168.0.2)' não pode ser estabelecida.
A impressão digital da chave RSA é SHA256: kd9mRkEGLo + RBBNpxKp7mInocF3 / Yl / 0fXRsGJ2JfYg.
Tem certeza de que deseja continuar se conectando (sim / não)?
Se você concordar, a seguinte linha será adicionada ao arquivo ~ / .ssh / known_hosts:
| 1 | CuXixZ + EWfgz40wpkMugPHPalyk = | = KNoVhur7z5NAZmNndtwWq0kN1SQ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCeiF4OOOUhWvOYrh / e4q91 + iz + i9S0s3M2LPq + GAhRlhKt5vKyEVd6x6m26cc98Y + SQXnCB9GWeVYk8jlFHEXnY4YWeWLDwXIhHBJYt5yz3j5Wkg95x + mPvO9FLSBk / Al2GbH5q6F + hZIlLmO6ciISmX4TtcG1sw4SwoTADrrhdM0OJd + c5CU8iqCbc6PznYbLZXCvqPZTWeSbTLUcUu1Ti + 7xGwT8DF + tIyLFcU + zxd0QnwJIbNvewkHs0LsMOWFVPz / Nd0XiVXimX + ugCDBZ / 4q8NUwH9SGzCMAvnnr + D1I8X2vhSuRsTsQXL5P3vf8elDxPdDrMJzNtlBCbLWzV
Aqui, três elementos são escritos com um espaço: um hash em nome do servidor, o nome do algoritmo assimétrico usado e a chave pública do servidor. Vamos separá-los.

E se você ler as instruções
De fato, de acordo com o manual da Ubunt, pode haver mais 2 campos, também separados por espaços:
  • no início da linha, pode haver uma nota “@ cert-Authority” ou “@ revevoked”, o que significa, respectivamente, que a chave pública da CA está gravada nesta linha ou que essa chave foi revogada e não pode ser usada.
  • pode haver um comentário arbitrário no final da linha


Nome do servidor


No exemplo, o hash em nome do servidor (host) se parece com o seguinte:
| 1 | CuXixZ + EWfgz40wpkMugPHPalyk = | KNoVhur7z5NAZmNndtwWq0kN1SQ =
De fato, o nome do host em texto não criptografado ou uma máscara que especifica o conjunto de nomes válidos pode ser gravado aqui. Mas meu nome padrão de hash é salvo. O registro é dividido em 3 partes pelo símbolo "|". A primeira parte é o algoritmo de hash. "1" corresponde ao HMAC-SHA1 (não vi outros). A segunda parte é salt (chave para HMAC). A terceira parte é o próprio hash (saída HMAC).

Verificar
from base64 import b64decode import hmac salt = b64decode("CuXixZ+EWfgz40wpkMugPHPalyk=") host = b'192.168.0.2' hash = hmac.HMAC(salt, host, 'sha1').digest() print(b64encode(hash).decode()) 

> 'KNoVhur7z5NAZmNndtwWq0kN1SQ ='

Algoritmo assimétrico


O RFC-4253 lista 4 algoritmos assimétricos: ssh-dss (obrigatório por padrão, mas considerado fraco e desativado por padrão desde o OpenSSH7.0), ssh-rsa (recomendado), pgp-sign-rsa (opcional), pgp- sign-dss (opcional). Por padrão, as chaves dos dois primeiros tipos são geradas no Linux para algoritmos de curva elíptica não mencionados na RFC. O último é preferido, mas o cliente pode selecionar o algoritmo com a opção HostKeyAlgorithms.

Como verificar a impressão digital da chave desejada (não o padrão)
Isso pode ser útil se, por exemplo, quando você entrar no servidor pela primeira vez, desejar verificar a impressão digital da chave e conhecer apenas a impressão digital da chave ssh-rsa. Então você pode se conectar com este comando:
ssh root@192.168.0.2 -o HostKeyAlgorithms = ssh-rsa

Se você também precisar especificar um algoritmo de hash de chave, poderá usar a opção FingerprintHash. Por exemplo, se apenas o md5 for conhecido no ssh-rsa, você poderá se conectar assim:
ssh root@192.168.0.2 -o HostKeyAlgorithms = ssh-rsa -o FingerprintHash = md5


Chave pública


A chave pública em known_hosts é a mesma que a registrada no arquivo /etc/ssh/ssh_host_rsa_key.pub no servidor (substitua o nome do algoritmo usado em vez de rsa). Se você remover a codificação Base64, o nome do algoritmo e os principais componentes reais serão inseridos.

Por que não remover Base64
 b'\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x03\x01\x00\x01\x00\x00\x01\x01\x00\x9e\x88^\x0e8\xe5!Z\xf3\x98\xae\x1f\xde\xe2\xafu\xfa,\xfe\x8b\xd4\xb4\xb3s6,\xfa\xbe\x18\x08Q\x96\x12\xad\xe6\xf2\xb2\x11Wz\xc7\xa9\xb6\xe9\xc7=\xf1\x8f\x92Ay\xc2\x07\xd1\x96yV$\xf29E\x1cE\xe7c\x86\x16yb\xc3\xc1r!\x1c\x12X\xb7\x9c\xb3\xde>V\x92\x0fy\xc7\xe9\x8f\xbc\xefE- d\xfc\tv\x19\xb1\xf9\xab\xa1~\x85\x92%.c\xbar"\x12\x99~\x13\xb5\xc1\xb5\xb3\x0e\x12\xc2\x84\xc0\x0e\xba\xe1t\xcd\x0e%\xdf\x9c\xe4%<\x8a\xa0\x9bs\xa3\xf3\x9d\x86\xcbep\xaf\xa8\xf6SY\xe4\x9bL\xb5\x1cR\xedS\x8b\xee\xf1\x1b\x04\xfc\x0c_\xad#"\xc5qO\xb3\xc5\xdd\x10\x9f\x02Hl\xdb\xde\xc2A\xec\xd0\xbb\x0c9aU??\xcdwE\xe2Ux\xa6_\xeb\xa0\x080Y\xff\x8a\xbc5L\x07\xf5!\xb3\x08\xc0/\x9ez\xfe\x0fR<_k\xe1J\xe4lN\xc4\x17/\x93\xf7\xbd\xff\x1e\x94<Ot:\xcc\'3m\x94\x10\x9b-l\xd5' 
Pode-se ver que existem 4 bytes nos quais o comprimento do campo é gravado, o próprio campo etc. O primeiro campo é o nome do algoritmo, o restante depende do algoritmo específico. Na chave acima, 3 campos:
 b'ssh-rsa' -  b'\x01\x00\x01' -   b'\x00\x9e\x88^\x0e8\xe5!Z\xf3\x98\xae\x1f\xde\xe2\xafu\xfa,\xfe\x8b\xd4\xb4\xb3s6,\xfa\xbe\x18\x08Q\x96\x12\xad\xe6\xf2\xb2\x11Wz\xc7\xa9\xb6\xe9\xc7=\xf1\x8f\x92Ay\xc2\x07\xd1\x96yV$\xf29E\x1cE\xe7c\x86\x16yb\xc3\xc1r!\x1c\x12X\xb7\x9c\xb3\xde>V\x92\x0fy\xc7\xe9\x8f\xbc\xefE- d\xfc\tv\x19\xb1\xf9\xab\xa1~\x85\x92%.c\xbar"\x12\x99~\x13\xb5\xc1\xb5\xb3\x0e\x12\xc2\x84\xc0\x0e\xba\xe1t\xcd\x0e%\xdf\x9c\xe4%<\x8a\xa0\x9bs\xa3\xf3\x9d\x86\xcbep\xaf\xa8\xf6SY\xe4\x9bL\xb5\x1cR\xedS\x8b\xee\xf1\x1b\x04\xfc\x0c_\xad#"\xc5qO\xb3\xc5\xdd\x10\x9f\x02Hl\xdb\xde\xc2A\xec\xd0\xbb\x0c9aU??\xcdwE\xe2Ux\xa6_\xeb\xa0\x080Y\xff\x8a\xbc5L\x07\xf5!\xb3\x08\xc0/\x9ez\xfe\x0fR<_k\xe1J\xe4lN\xc4\x17/\x93\xf7\xbd\xff\x1e\x94<Ot:\xcc\'3m\x94\x10\x9b-l\xd5' -  N (0x101 * 8 = 2048 ) 


Impressão digital


A impressão digital da chave que se propõe a verificar na primeira conexão é o hash correspondente (no exemplo, SHA256) da chave pública do último parágrafo e do /etc/ssh/ssh_host_rsa_key.pub codificado em base64 para o hash das funções da família SHA ou em hexadecimal para MD5.

Consideramos
 from hashlib import sha256 from base64 import b64decode, b64encode pub_key_bin = b64decode("AAAAB3NzaC1yc2EAAAADAQABAAABAQCeiF4OOOUhWvOYrh/e4q91+iz+i9S0s3M2LPq+GAhRlhKt5vKyEVd6x6m26cc98Y+SQXnCB9GWeVYk8jlFHEXnY4YWeWLDwXIhHBJYt5yz3j5Wkg95x+mPvO9FLSBk/Al2GbH5q6F+hZIlLmO6ciISmX4TtcG1sw4SwoTADrrhdM0OJd+c5CU8iqCbc6PznYbLZXCvqPZTWeSbTLUcUu1Ti+7xGwT8DF+tIyLFcU+zxd0QnwJIbNvewkHs0LsMOWFVPz/Nd0XiVXimX+ugCDBZ/4q8NUwH9SGzCMAvnnr+D1I8X2vhSuRsTsQXL5P3vf8elDxPdDrMJzNtlBCbLWzV") hash = sha256(pub_key_bin).digest() fingerprint = b64encode(hash) print(fingerprint) > b'kd9mRkEGLo+RBBNpxKp7mInocF3/Yl/0fXRsGJ2JfYg=' + iz + i9S0s3M2LPq + GAhRlhKt5vKyEVd6x6m26cc98Y + SQXnCB9GWeVYk8jlFHEXnY4YWeWLDwXIhHBJYt5yz3j5Wkg95x + mPvO9FLSBk / Al2GbH5q6F + hZIlLmO6ciISmX4TtcG1sw4SwoTADrrhdM0OJd + c5CU8iqCbc6PznYbLZXCvqPZTWeSbTLUcUu1Ti + 7xGwT8DF + tIyLFcU + zxd0QnwJIbNvewkHs0LsMOWFVPz / Nd0XiVXimX + ugCDBZ / 4q8NUwH9SGzCMAvnnr + D1I8X2vhSuRsTsQXL5P3vf8elDxPdDrMJzNtlBCbLWzV") from hashlib import sha256 from base64 import b64decode, b64encode pub_key_bin = b64decode("AAAAB3NzaC1yc2EAAAADAQABAAABAQCeiF4OOOUhWvOYrh/e4q91+iz+i9S0s3M2LPq+GAhRlhKt5vKyEVd6x6m26cc98Y+SQXnCB9GWeVYk8jlFHEXnY4YWeWLDwXIhHBJYt5yz3j5Wkg95x+mPvO9FLSBk/Al2GbH5q6F+hZIlLmO6ciISmX4TtcG1sw4SwoTADrrhdM0OJd+c5CU8iqCbc6PznYbLZXCvqPZTWeSbTLUcUu1Ti+7xGwT8DF+tIyLFcU+zxd0QnwJIbNvewkHs0LsMOWFVPz/Nd0XiVXimX+ugCDBZ/4q8NUwH9SGzCMAvnnr+D1I8X2vhSuRsTsQXL5P3vf8elDxPdDrMJzNtlBCbLWzV") hash = sha256(pub_key_bin).digest() fingerprint = b64encode(hash) print(fingerprint) > b'kd9mRkEGLo+RBBNpxKp7mInocF3/Yl/0fXRsGJ2JfYg=' 

Vemos que o hash realmente corresponde à impressão digital mostrada durante a primeira conexão (citação no início do artigo), exata ao símbolo "=" no final.

Aqui está um pequeno programa para encontrar hosts no arquivo known_hosts, que apareceu durante os experimentos.

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


All Articles