Facebook
Twitter
Google+
Kommentare
0

Dieser Schlüssel zerstört sich in 30 Sekunden selbst

Gastartikel von Oliver Sperke.

Ich bin 34 Jahre alt und seit 10 Jahren selbständiger Webentwickler. Mein Fokus liegt dabei auf der Erstellung, Beratung und Optimierung in den Bereichen High Performance, Usability und Sicherheit in den gängigsten Internetsprachen: PHP, HTML, Javascript und CSS.

Nachdem ich ja in den letzten Wochen über den sicheren Umgang mit Passwörtern in Webprojekten erzählt habe, soll es heute mal um etwas anderes gehen (aber trotzdem um das Thema Sicherheit). Wenn man oft auf fremden oder eigenen Servern arbeitet, kommt man an OpenSSH eigentlich nicht vorbei. Und wenn man dazu noch so faul ist wie ich (und vermutlich die meisten von Euch auch), hat man keine dutzenden Dateien mit Passwörtern, sondern wickelt die gesamten Loginvorgänge mit Hilfe von öffentlichen und privaten Schlüsseln ab. Dieses Verfahren ist nicht nur bequem, es bietet auch zusätzliche Sicherheit, da man nicht in Versuchung kommt, einfache Passwörter zu verwenden. Ausserdem ist die eigene Passwortliste schon von Haus aus verschlüsselt.

Das Verfahren hat aber für einen Serverbetreiber Nachteile. Der öffentliche Schlüssel muss auf dem Server hinterlegt werden. Ausserdem muss man sobald der Zugang nicht mehr benötigt wird, nachsehen, ob ein Benutzer sich vielleicht eigene Schlüssel hinterlegt hat und natürlich muss man ihm den Zugang manuell sperren.

Alle diese Vorgänge sind lästig und zeitaufwendig und bergen Gefahren, vor allem dann, wenn man die Zugänge von vielen Benutzern verwalten muss. Schnell hat man eine Zeile in der „authorized_keys“ Datei für einen Benutzer übersehen und handelt sich damit dauerhaft ungebetene Gäste ein. Seit OpenSSH 5.6 gibt es nicht nur die Möglichkeit, öffentliche und private Schlüssel zu hinterlegen, sondern den öffentlichen Schlüssel zu signieren. Dieses Verfahren der Signierung oder Zertifizierung bietet uns gewaltige Vorteile.

Der Server kann bei einer Signierung erkennen, ob ein Schlüssel nur für einen gewissen Zeitraum gültig sein soll oder schon abgelaufen ist und ob gewisse Rechte, z. B. zum X11 Forwarding oder Port Weiterleitung erteilt wurden oder nicht. Ausserdem müssen wir die Public Keys der Nutzer nicht mehr hinterlegen und unser Privatekey ist quasi unangreifbar. Dieses Verfahren benötigt fertig eingerichtet nicht mal mehr einen Login auf dem Server zur Erstellung neuer Zugänge.

Wichtiger Hinweis und Ausgangssituation

Lest bitte erst den ganzen Text, damit Ihr nicht in der Mitte stecken bleibt. Wenn Ihr nicht regelmäßig auf Linuxsystemen arbeitet, dann richtet euch eine virtuelle Maschine ein, die Ihr nach Lust und Laune kaputt konfigurieren könnt. Das Verfahren nutze ich selbst auf meinen Servern, wenn Ihr Euch trotzdem aussperrt, dann ist das nicht meine Schuld, bei mir geht es ja. Man kann das Verfahren auch auf einem Rechner testen.

Falls Euer Zielrechner nicht greifbar für Euch ist, also irgendwo im Rechenzentrum steht, lasst die Passwortauthentifizierung an und loggt Euch zusätzlich auf einer anderen Konsole ein. Lasst das Fenster offen. Sollte etwas schief gehen, könnt Ihr es in diesem Fenster immer noch reparieren. Diese Anleitung richtet sich eindeutig an erfahrende Nutzer und ist nichts für Hobbyadmins und „Menschen mit schwachem Herz“.

Server und Client sind bei mir beide Linuxrechner – für Windows bin ich kein Fachmann. Da aber OpenSSH auch unter Windows arbeitet, dürfte die Konfiguration letzendlich in etwa die gleiche sein.

Alle Einstellungen sind lediglich Vorschläge und nicht verbindlich. Verbesserungen sind natürlich willkommen, eigenes Nachdenken erwünscht. Als Testsystem habe ich Debian Squeeze auf dem Server und bei mir zu Hause ArchLinux. Bei Debian muss der SSH Server aus dem „unstable“ Zweig installiert werden (libssl, openssh-server, openssh-client), da es dort noch kein aktuelles Paket in testing oder stable gibt. Als Mindestversion empfehle ich OpenSSH 5.8, Version 5.6 sollte aber theoretisch auch funktionieren.

Ich arbeite zunächst als root während der Einrichtung bis ich etwas anderes sage. Wer das nicht möchte, muss überall sudo vor die Befehle schreiben. Sollte noch kein SSH Server und/oder Client installiert sein, fangen wir damit an.

Auf dem Server (root)

apt-get install openssh-server openssh-client libssl

Auf dem Client (root)

apt-get install openssh-client

Nach kurzer Wartezeit ist unser SSH Server fertig eingerichtet und gestartet.

Was werden wir tun?

  1. Grundlegende (sichere) Konfiguration des SSH Dienstes
  2. Sperren des SSH Login für root
  3. Anlegen und Einrichten eines neuen Benutzers zum Login
  4. Zugang für diesen Benutzer nur mit gültigem signiertem Schlüssel

Die Konfiguration

Zunächst sichern wir die aktuelle Konfiguration. Dann editieren wir die sshd_config mit nano (joe, vi usw. gehen natürlich auch).

Auf dem Server (root)

cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
nano /etc/ssh/sshd_config

Innerhalb der Datei ändere ich die Einstellungen unter dem Punkt Authentification auf die angegebenen Werte. die LoginGraceTime kann auf 10 Sekunden herunter gesetzt werden, da ein Zugriff mit Passwörtern nicht genutzt wird und meine Schlüssel vom ssh-agent verwaltet werden. Den root Login verbiete ich, denn ich will es „Brute Forcern“ etwas schwerer machen. Die Einstellungen für StrictModes, RSAAuthentication, PubkeyAuthentication bleiben gleich. PasswordAuthentication setze ich hier schon auf no (siehe Hinweise). Wenn Ihr wollt, könnt Ihr auch mit AllowUsers user1 user2 usw. eine „Whitelist“ für erlaubte Loginnamen fest legen. Das bietet aber auch nicht mehr Sicherheit – nur die Fehlermeldung ändert sich.

Die Werte für AuthorizedKeysFile, AuthorizedPrincipalsFile und TrustedUserCAKeys fügen wir hinzu. In der AuthorizedKeysFile stehen normalerweise die Publickeys der Benutzer. Da wir die aber hier nicht brauchen, ändern wir den Wert auf /dev/null. So kann sich kein Benutzer eigene Zugänge hinterlegen. TrustedUserCAKeys ist der öffentliche Teil unseres Zertifikats. In der AuthorizedPrincipalsFile stehen alle Benutzer, die in den Zertifikaten hinterlegt werden. Dazu später noch mehr.

# Authentication:
LoginGraceTime 10
PermitRootLogin no
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes

AuthorizedKeysFile /dev/null
TrustedUserCAKeys /etc/ssh/trusted_ca_keys
AuthorizedPrincipalsFile %h/.ssh/authorized_ca_user

PasswordAuthentication no

Die Einstellungen übernehmen wir mit einem SSH Neustart. Wenn Ihr Euch nicht sicher seid, wartet noch. Die Änderungen könnt Ihr jederzeit rückgängig machen, indem ihr die .bak Datei zurück kopiert und dann ssh neu startet.

Auf dem Server (root)

/etc/init.d/ssh restart

Der authorisierte Benutzer

Als nächstes legen wir einen neuen Benutzer an. Den nenne ich jetzt einfach mal login, weil er nur dafür da ist, sich auf dem Server anzumelden. Bevor Ihr versucht anonsphere.com zu brute forcen – da hab ich nen anderen Benutzer – ausserdem werde Ihr nach 3 Versuchen gebannt. :-) Die zweite Zeile ist optional. Ihr könnt natürlich auch ein Passwort für den Benutzer hinterlegen, aber ich habe keine Lust, dass jedesmal einzugeben. Wer sich als dieser Benutzer einloggen kann, könnte eh unbemerkt keylogger o. ä. installieren. Mir persönlich reicht der abgesicherte Zugang. Wenn der Benutzer eingeschränkt handeln soll, also nicht zum root werden darf, ändert den Befehl von -G users,admin auf -g users

Auf dem Server (root)

useradd -c "Login" -d /home/login -G users,admin -u 1003 -m -s /bin/bash login
passwd --delete login

Der normale Schlüssel

Auf Eurem Clientsystem erzeugen wir für unseren Benutzer einen Schlüssel, falls Ihr schon einen habt, springt zum nächsten Kapitel.

Auf dem Client (Benutzer)

ssh-keygen -t rsa -b 4096 -f id_rsa

Verschiebt den private Schlüssel in den Ordner ~/.ssh/id_rsa. Der Publickey wird nicht auf dem Server hinterlegt!

Auf dem Client (Benutzer)

mkdir ~/.ssh/
mv id_rsa ~/.ssh/id_rsa

Der signierte Schlüssel

Zum Erstellen der Zertifikate brauchen wir noch ein Schlüsselpaar. Den Ablauf kennen wir ja schon. Den Inhalt des öffentlichen Schlüssel hinterlegen wir auf dem Server in der Datei trusted_ca_keys. Dann wechseln wir auf unseren Benutzer und hinterlegen die ID des Zertifikats („principal“), die erlaubt sein sollen – dieser muss nicht mit dem Benutzernamen übereinstimmen. Auf dem Server muss nur der Publickey des Zertifikats liegen.

Auf dem Client oder Server (Benutzer)

ssh-keygen -t rsa -b 4096 -f zertifikat_rsa

Auf dem Server (root)

cat zertifikat_rsa.pub >> /etc/ssh/trusted_ca_keys
su login
mkdir ~/.ssh/
echo "oliver" >> ~/.ssh/authorized_ca_user

Die einzige wichtige Datei ist die zertifikat_rsa. Diese muss gesichert werden (auch mehrfach) und möglichst weit weg von direktem Zugriff (Container, USB Stick, etc.). Alle anderen Dateien sind uninteressant! Wir haben also jetzt unsere Vorbereitungen getroffen. Als letztes muss noch Euer Publickey (aus „Der normale Schlüssel“) signiert werden. Das macht ihr mit folgender Zeile. I ist der Name der Zertifizierung und steht später im auth.log. n ist der principal, also der Benutzername, für den das Zertifikat ausgestellt ist und der in der authorized_ca_user hinterlegt wurde.

ssh-keygen -s zertifikat_rsa -I MeinLogin -n oliver .ssh/id_rsa.pub
ssh-add .ssh/id_rsa

Falls Ihr den SSH Agent benutzt, fügt danach den Schlüssel hinzu mit ssh-add .ssh/id_rsa.

Aufräumen

Jetzt könnte es passiert sein, dass die Rechte nicht korrekt gesetzt wurden bei unseren Aktionen. Dieses Problem erledigen wir mit der beliebten „Holzhammermethode“, damit unser Setup sicher ist. Wir gehen zurück auf den root Account auf dem Server und setzen dann unsere Rechte.

Auf dem Server (root)

chown -R root:root /etc/ssh/*
chmod 600 /etc/ssh/*

Auf dem Client (Benutzer)

chmod 700 ~/.ssh
chmod 600 ~/.ssh/*

Der Login sollte nun funktionieren. Wenn nicht, gibt die Datei /var/log/auth.log (Client und Server) weitere Informationen. Falls da nichts brauchbares steht, erhöht in der ssh_config/sshd_config den LogLevel auf DEBUG3. Fast immer sind irgendwo die Rechte falsch. Wenn bis hier hin alles funktioniert, können wir jetzt ein zeitlich eingeschränktes Zertifikat erzeugen. Dafür benutzen wir diese Zeile.

Auf dem Client (Benutzer)

ssh-keygen -s zertifikat_rsa -I MeinLogin -n oliver -V +5m .ssh/id_rsa.pub

Der Zugang wäre damit fünf Minuten gültig. Probiert es aus! Meldet Euch auf dem Server an, meldet Euch ab und schaut, ob Ihr Euch nach 5 Minuten noch anmelden könnt. Wenn Ihr mit dem Prinzip warm geworden seid, könnt Ihr natürlich auch fremde Publickeys signieren. Der Befehl sieht dann z. B. so aus:

ssh-keygen -s zertifikat_rsa -I Zeitarbeiter -n zeitarbeiter -V +1d fremderPubkey.pub

Neben der Zeit könnt Ihr auch seine Rechte, wie Port- oder X11-Forwarding einschränken. Mehr Infos bekommt Ihr mit

man ssh-keygen

Auf dem Server müsst Ihr dann in der Datei /home/login/authorized_ca_user auf dem Server den Benutzer zeitarbeiter in einer neuen Zeile hinterlegen. Ihr könnt jede ID mehrfach verwenden. So könntet Ihr natürlich auch Signaturen vorher entwerten, indem Ihr einen verwendeten Priincipal löscht. Um einem neuem Benutzer Zugang zu erteilen, benötigt Ihr seinen Publickey. Diesen signiert Ihr mit der zertifikat_rsa und schickt ihm die *-cert.pub Datei zurück. Kein Login nötig!

Was geht? Was geht nicht?

Mit Hilfe der Signaturen ist es nun endlich möglich, Zugänge zu Servern zu erteilen, die nach einer gewissen Zeit selbst verfallen, ab einem gewissem Zeitpunkt gültig sind oder Aktionen verbieten, ohne in der sshd_config Änderungen vorzunehmen. Das Verfahren eignet sich u. a. für die Vergabe von Serverzugängen für Wartungsarbeiten an der Datenbank oder zur Einrichtung von Software, die vom Benutzer genutzt wird. Ausserdem natürlich auch für die sichere Vergabe von SFTP oder FISH Zugänge mit denen der Benutzer seine Dateien ändern kann. Wenn jemand für ein Jahr bezahlt und nicht verlängert, haben wir keine Arbeit mehr damit. Verlängert er den Zugang, können wir ihm einfach lokal ein neues Zertifikat generieren.

Der größte Vorteil ist aber, dass Euer Privatekey quasi nicht mehr kompromitiert werden kann. Ich benutze den RSA Schlüssel nur für meine Serverzugänge. Sollte er mir aus irgendwelchen Gründen gestohlen werden und das Passwort gleich dazu, benenne ich einfach den principal um und erzeuge mir ein neues Zertifikat. Meinen Privatekey kann sich derjenige dann ausdrucken und an die Wand hängen, weil der ist für den Zugang völlig unerheblich. Wichtig ist nur die zertifikat_rsa, die muss geschützt werden und diese liegt natürlich sicher in einer verschlüsselten Datei.

Als Einschränkung müssen wir allerdings hin nehmen, dass das Verfahren bisher nur in aktuellen OpenSSH Versionen integriert ist, was evtl. den Zugang durch Programme wie PuTTY oder WinSCP erschwert. Für Windows habe ich generell noch nach keiner Lösung gesucht. Es kann also sein, dass es schon funktioniert, muss aber nicht – Infos bitte in die Kommentare. Unter Linux funktioniert das Verfahren mit allen Programmen, die auf der Basis von OpenSSH arbeiten, also eigentlich mit allen.

Einen Hinweis noch
Falls Ihr auf eure Server fail2ban einsetzt, müsst Ihr aus der Filterdatei für ssh die Zeile mit „Invalid Publickey“ entfernen oder auskommentieren, denn der ist durch den Verweis auf /dev/null natürlich immer falsch, auch wenn die Authentifizierung letzendlich erfolgreich ist (und ja, ich hatte beim ersten Mal auch nicht dran gedacht). In diesem Fall solltet Ihr auch eine Whitelist setzen, denn ansonsten werden Benutzer mit falschem Namen nicht immer gebannt.

flattr this!

Über den Autor

Oliver Klee

Oliver Klee ist Web Developer Frontend bei einer Agentur in der nähe von Frankfurt und ist dort verantwortlich für Technische Konzeption und Programmierung interaktiver Frontends in komplexen Internet- und Intranet-Projekten sowie die Realisierung von Online-Applikationen.

Link erfolgreich vorgeschlagen.

Vielen Dank, dass du einen Link vorgeschlagen hast. Wir werden ihn sobald wie möglich prüfen. Schließen