Was ist in der Datei .ssh / unknown_hosts geschrieben?


Jedes Mal, wenn wir über das ssh-Protokoll eine Verbindung zum Server herstellen, prüft der ssh-Client, ob der öffentliche Schlüssel für diesen Server mit dem letzten Mal übereinstimmt (zumindest wird empfohlen, den ssh-Standard auszuführen). In OpenSSH wird eine Liste bekannter Serverschlüssel in der Datei unknown_hosts gespeichert. Unter katom kurz darüber, was und wie genau dort gespeichert ist.

Alle Experimente wurden unter Linux (Debian / Mint / Ubuntu) durchgeführt. Ich kann nicht für den Speicherort und den Inhalt von Dateien in anderen Betriebssystemen bürgen.

Wenn wir zum ersten Mal eine Verbindung zum SSH-Server herstellen, sehen wir ungefähr Folgendes:
Die Authentizität des Hosts '192.168.0.2 (192.168.0.2)' kann nicht festgestellt werden.
Der Fingerabdruck des RSA-Schlüssels lautet SHA256: kd9mRkEGLo + RBBNpxKp7mInocF3 / Yl / 0fXRsGJ2JfYg.
Sind Sie sicher, dass Sie die Verbindung fortsetzen möchten (Ja / Nein)?
Wenn Sie damit einverstanden sind, wird die folgende Zeile zur Datei ~ / .ssh / unknown_hosts hinzugefügt:
| 1 | CuXixZ + EWfgz40wpkMugPHPalyk = | KNoVhur7z5NAZmNndtwWq0kN1SQ = ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCeiF4OOOUhWvOYrh / e4q91 + iz + i9S0s3M2LPq + GAhRlhKt5vKyEVd6x6m26cc98Y + SQXnCB9GWeVYk8jlFHEXnY4YWeWLDwXIhHBJYt5yz3j5Wkg95x + mPvO9FLSBk / Al2GbH5q6F + hZIlLmO6ciISmX4TtcG1sw4SwoTADrrhdM0OJd + c5CU8iqCbc6PznYbLZXCvqPZTWeSbTLUcUu1Ti + 7xGwT8DF + tIyLFcU + zxd0QnwJIbNvewkHs0LsMOWFVPz / Nd0XiVXimX + ugCDBZ / 4q8NUwH9SGzCMAvnnr + D1I8X2vhSuRsTsQXL5P3vf8elDxPdDrMJzNtlBCbLWzV
Hier werden drei Elemente mit einem Leerzeichen geschrieben: ein Hash im Namen des Servers, der Name des verwendeten asymmetrischen Algorithmus und der öffentliche Schlüssel des Servers. Nehmen wir sie auseinander.

Und wenn Sie die Anweisungen lesen
Tatsächlich kann es laut Handbuch für Ubunt zwei weitere Felder geben, die ebenfalls durch Leerzeichen getrennt sind:
  • Am Anfang der Zeile befindet sich möglicherweise der Hinweis "@ cert-Authority" oder "@revoked". Dies bedeutet, dass der öffentliche Schlüssel der Zertifizierungsstelle in diese Zeile geschrieben ist oder dass dieser Schlüssel widerrufen wurde und nicht verwendet werden kann.
  • Möglicherweise steht am Ende der Zeile ein beliebiger Kommentar


Servername


Im Beispiel sieht der Hash im Namen des Servers (Hosts) folgendermaßen aus:
| 1 | CuXixZ + EWfgz40wpkMugPHPalyk = | KNoVhur7z5NAZmNndtwWq0kN1SQ =
Tatsächlich kann hier der Hostname im Klartext oder eine Maske geschrieben werden, die den Satz gültiger Namen angibt. Aber mein Standard-Hash-Name wird gespeichert. Der Datensatz ist durch das Symbol "|" in 3 Teile unterteilt. Der erste Teil ist der Hashing-Algorithmus. "1" entspricht HMAC-SHA1 (ich habe andere nicht gesehen). Der zweite Teil ist Salz (Schlüssel für HMAC). Der dritte Teil ist der Hash selbst (HMAC-Ausgabe).

Überprüfen Sie
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 ='

Asymmetrischer Algorithmus


RFC-4253 listet 4 asymmetrische Algorithmen auf: ssh-dss (standardmäßig obligatorisch, aber seit OpenSSH7.0 als schwach und standardmäßig deaktiviert), ssh-rsa (empfohlen), pgp-sign-rsa (optional), pgp- sign-dss (optional). Standardmäßig werden die Schlüssel der ersten beiden Typen unter Linux für elliptische Kurvenalgorithmen generiert, die im RFC nicht erwähnt werden. Letzteres wird bevorzugt, aber der Client kann den Algorithmus mit der Option HostKeyAlgorithms auswählen.

So überprüfen Sie den gewünschten (nicht den Standard-) Tastenfingerabdruck
Dies kann nützlich sein, wenn Sie beispielsweise beim ersten Aufrufen des Servers den Fingerabdruck des Schlüssels überprüfen möchten und nur den Fingerabdruck des ssh-rsa-Schlüssels kennen. Dann können Sie sich mit diesem Befehl verbinden:
ssh root@192.168.0.2 -o HostKeyAlgorithms = ssh-rsa

Wenn Sie auch einen Schlüssel-Hashing-Algorithmus angeben müssen, können Sie die Option FingerprintHash verwenden. Wenn beispielsweise nur md5 von ssh-rsa bekannt ist, können Sie eine Verbindung wie folgt herstellen:
ssh root@192.168.0.2 -o HostKeyAlgorithms = ssh-rsa -o FingerprintHash = md5


Öffentlicher Schlüssel


Der öffentliche Schlüssel in unknown_hosts ist der gleiche wie der in der Datei /etc/ssh/ssh_host_rsa_key.pub auf dem Server aufgezeichnete (ersetzen Sie den Namen des verwendeten Algorithmus anstelle von rsa). Wenn Sie die Base64-Codierung entfernen, werden im Inneren wieder der Name des Algorithmus und die tatsächlichen Schlüsselkomponenten angezeigt.

Warum nicht Base64 entfernen?
 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' 
Es ist ersichtlich, dass es 4 Bytes gibt, in die die Länge des Feldes geschrieben wird, dann das Feld selbst usw. Das erste Feld ist der Name des Algorithmus, der Rest hängt vom jeweiligen Algorithmus ab. In der obigen Taste 3 Felder:
 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 ) 


Fingerabdruck


Der Fingerabdruck des Schlüssels, dessen Überprüfung bei der ersten Verbindung vorgeschlagen wird, ist der entsprechende Hash (im Beispiel SHA256) aus dem öffentlichen Schlüssel aus dem letzten Absatz und aus /etc/ssh/ssh_host_rsa_key.pub, der in base64 für den Hash der Funktionen der SHA-Familie oder in hex für MD5 codiert ist.

Wir überlegen
 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=' 

Wir sehen, dass der Hash wirklich mit dem Fingerabdruck übereinstimmt, der während der ersten Verbindung angezeigt wurde (Zitat am Anfang des Artikels), bis zum Symbol "=" am Ende.

Hier ist ein kleines Programm zum Finden von Hosts in der Datei unknown_hosts, die während der Experimente angezeigt wurde.

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


All Articles