Google Authenticator als PAM-Modul im OpenSSH-Server

Google Authenticator

Die Umgebung

Folgendes Setup ist für diesen Artikel angedacht:

  • Logins sind nur schlüsselbasiert möglich.
  • Wurde Google Authenticator für einen Benutzer eingerichtet, muss es verwendet werden
  • Liegt kein Google Authenticator Profil für einen Benutzer vor, funktioniert der Login auch weiterhin mit Private Key

Am Ende noch ein kleiner Hinweis für die, die es lieber ohne Schlüssel „tun“. :-)
Nachdem wir geschätzt 10³ Artikel zu diesem Thema gelesen haben, versuche ich es etwas zu individualisieren, da in den Kommentaren immer die selben Fragen auftauchten.

Einrichtung

Ab Debian Jessie ist das Google Auth. PAM-Modul auch im offiziellen Repository Debians enthalten.
Das Modul ist nicht neu und sollte inzwischen in vielen Distributionen angekommen sein.
Für Ubuntu/Debian:

apt-get install libpam-google-authenticator

Das PAM-Modul kann nicht nur theoretisch, sondern auch praktisch in jedem Dienst Anwendung finden, der im Verzeichnis /etc/pam.d/ hierfür hinterlegt ist.
Für die erweiterte SSH-Authentifizierung, bearbeite ich zuerst die Datei /etc/pam.d/sshd.
Direkt am Anfang, sprich in erster Zeile, das Folgende einfügen:

/etc/pam.d/sshd:

auth [success=done new_authtok_reqd=done default=die] pam_google_authenticator.so nullok

Dieser Eintrag bewirkt, sollte der Google Authenticator für den Benutzer eingerichtet sein, dass dieser unbedingt zu benutzen ist.
Wurde der Authenticator nicht eingerichtet, kann der Benutzer sich trotzallem anmelden, da „nullok“.

„@include common-auth“ wird übergangen, da vorher schon der Wert „success=done“ für „auth“ zurückgegeben wird.
Ohne „success=done“ (zum Beispiel „success=ok“), würde zusätzlich die Passwortabfrage greifen (angenommen es ist in der SSHd-Konfiguration erlaubt!).

In der Konfigurationsdatei des OpenSSH-Servers /etc/ssh/sshd_config werden unten stehende Änderungen vorgenommen.

/etc/ssh/sshd_config:

# Auch wenn das Einloggen als root-Benutzer nur mit einem Private Key + Google Auth.
# möglich sein soll, muss dieser Eintrag "yes" und nicht "without-password" lauten. 
# Kein root-Login erwünscht? Dann "no".
PermitRootLogin yes 

# Das Google Auth. Modul arbeitet als "Challenge" zwischen User und SSHd, daher "yes".
ChallengeResponseAuthentication yes 

# Zuerst einen Key anfordern, danach den Bestätigungscode des Google Auth. eingeben lassen.
AuthenticationMethods publickey,keyboard-interactive:pam

# Standardeinstellung, jedoch noch einmal erwähnt, da wichtig.
UsePAM yes 

Beispielhaft eingeloggt als Benutzer „root“, möchte ich ein Google Authenticator Profil erstellen.
Ich habe mich dazu entschieden, den Vorgang mit Kommentaren zu versehen.

root@testing1:~# google-authenticator

# Ein zeitbasierter Code ist in der Regel erwünscht.
# Der Code muss also dann eingegeben werden, wenn er in der App als gültig angezeigt wird (etwa 30 Sekunden, die Dauer zeigt die App an!).
# Alternativ ist ein Code "counter-based", also abhängig davon, wie oft er verwendet wurde.
Do you want authentication tokens to be time-based (y/n) y

# An dieser Stelle erscheint ein Link und ein großer QR-Code. Der Link führt zum selben QR-Code, wie er schon auf dem Bildschirm sichtbar ist.
# Der QR-Code kann mit der App gescannt werden, so wird die Identität des Servers (der Schlüssel) automatisch hinterlegt.
https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/root@testing1%3Fsecret%3DMAI3Y7D5I6OLN3GS
[Abbildung QR-Code]

# Hier steht noch einmal der Schlüssel ("secret key"), der auch manuell in der App eingetragen werden kann. 
# Der "verification code" kann ignoriert werden.
# "emergency scratch codes" sind Einmal-Passwörter, die im Notfall angewendet werden können. Sie werden gelöscht, wenn ihr sie verwendet habt!
Your new secret key is: MAI3Y7D5I6OLN3GS
Your verification code is 756076
Your emergency scratch codes are:
  78313137
  36795830
  93407500
  10713953
  85166290

# Das Google Authenticator Profil für den aktuellen Benutzer ablegen? Ja!
Do you want me to update your "/root/.google_authenticator" file (y/n) y

# Einmal verwendet, muss bis zum nächsten Code gewartet werden (~30s), um sich noch einmal einzuloggen.
Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y

# Die App auf dem Handy muss zeitsynchron mit den Google Servern laufen, damit der angezeigte Code auch wirklich dann gültig ist, wenn ihr ihn seht!
# Meiner Meinung nach sind 90 Sekunden eine ausreichend große Abweichung, ansonsten "y" für 240 Sekunden eingeben.
By default, tokens are good for 30 seconds and in order to compensate for
possible time-skew between the client and the server, we allow an extra
token before and after the current time. If you experience problems with poor
time synchronization, you can increase the window from its default
size of 1:30min to about 4min. Do you want to do so (y/n) n

# Ist nicht verkehrt, selbst wenn ein Brute-Force Schutz bereits besteht: 3 Versuche in 30 Sekunden. 
If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting (y/n) y

Den Dienst anschließend neustarten…

service ssh restart

Und in einer zweiten SSH-Session die Verbindung testen! Bitte haltet immer ein Terminal auf, um euch nicht auszusperren.

…und ohne Schlüssel?

Wer schlüsselbasierte Authentifizierung doof findet, dem sei trotzallem eine Hilfestellung gegeben:

Wie erwähnt wird „done“ durch „ok“ ersetzt, um die nächste „auth“ Überprüfung NICHT zu überspringen:
/etc/pam.d/sshd:

auth [success=ok new_authtok_reqd=done default=die] pam_google_authenticator.so nullok

Es gilt Gleiches „wie mit“, außer…
/etc/ssh/sshd_config:

PasswordAuthentication yes
AuthenticationMethods keyboard-interactive:pam

3 Antworten auf “Google Authenticator als PAM-Modul im OpenSSH-Server

  1. tmolitor

    Auf meinem Server (aktuelles Debian Jessie) hat obige Anleitung in einer kleinen Abwandlung dazu geführt, dass alle Benutzer ohne .google_authenticator Datei im Homeverzeichnis, direkt eingeloggt wurden, statt die eigentlich gewünschte Passwortabfrage zu sehen zu bekommen.

    Das liegt wohl daran, dass das „nullok“ Argument des pam-Moduls dafür sorgt, dass es PAM_SUCCESS zurückgibt.
    Ein Patchen des google authenticators, sodass dieser PAM_IGNORE statt PAM_SUCCESS zurückliefert und folgende Zeile in der /etc/pam.d/sshd haben das gelöst:
    auth [success=done new_authtok_reqd=done ignore=ignore default=die] pam_google_authenticator.so nullok

    Die obige Anleitung reißt nicht direkt eine Sicherheitslücke auf, da die Zeile
    AuthenticationMethods publickey,keyboard-interactive:pam
    zwingend einen public key erforderlich macht.
    Setzt man diese Zeile allerdings in einen Match-Block, dann können sich plötzlich alle Nutzer außer root ohne Authentifizierung einloggen, wenn sie den google authenticator nicht konfiguriert haben:
    Match user root
    AuthenticationMethods publickey,keyboard-interactive:pam

    Der Patch ist das Einsetzen von PAM_IGNORE anstelle des PAM_SUCCESS an dieser Stelle:
    https://github.com/google/google-authenticator-libpam/blob/master/src/pam_google_authenticator.c#L1681

    Ich hoffe, ich konnte dem ein oder anderen helfen.
    Außerdem hilfreiche Literatur:
    http://www.rjsystems.nl/en/2100-pam-debian.php

  2. TingelTangel

    Hi,

    ich bin mir nicht sicher, woran es liegt, aber ich musste auf mehreren Systemen noch libpam-dev nachinstallieren, damit alles reibungslos lief.

    Vielleicht hilft der Tipp ja jemandem.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.