2FA und OpenLDAP mit Argon2 als Passwordhash

Im letzten Artikel ging es um die Einrichtung von TOTP für die Authentifizierung. In dem Artikel habe ich auf das OpenLDAP-Modul pw-totp gesetzt, da es auf den ersten Blick recht einfach einzurichten war. Ist es auch, nur habe ich dann erfahren, dass das Modul alt ist und nicht mehr genutzt werden soll, besser sei es das Modul otp zu nutzen, das neu ist und im OpenLDAP 2.5 bereitgestellt wird. Dann macht es Sinn auch gleich eine gute Verschlüsselung der Passwörter einzubringen. Der Tipp war, die Argon2-Verschlüsselung zu nutzen, das von OpenLDAP in der Version 2.5 voll unterstützt wird. Also, alles wieder auf Anfang und das ganze neu Eingerichtet. Als Grundlage für den OpenLDAP habe ich dieses mal Debian Experimental (Danke Roland für den Tipp) genutzt, denn da ist die Version 2.5.5 schon vorhanden. Also jeder der das hier nachbauen will, ist nicht mehr auf den Bau des OpenLDAP angewiesen. Leider ist das Module autoca hier nicht enthalten, sprich die Einrichtung der Client-Zertifikate aus dem letzten Artikel klappt hier noch nicht.

Als Pakete habe ich installiert:

  • slapd
  • ldap-utils
  • argon2

Debian generiert sofort eine dynamische Konfiguration für den OpenLDAP, auf die ich auch aufgesetzt habe. Mein erst Schritt war dann den Passwordhash {ARGON2} einzurichten. Dafür wird das entsprechende Modul im OpenLDAP benötigt. Mit der folgenden LDIF-Datei wird das Modul geladen:

dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: {1}argon2.la

Anschließend kann der Passwordhash mit der folgenden LDIF-Datei gesetzt werden:

dn: olcDatabase={-1}frontend,cn=config
changetype: modify
add: olcPasswordHash
olcPasswordHash: {ARGON2}

Wichtig ist hier, dass der Passwordhash in der Datenbank {-1}frontend,cn=config eingetragen wird und nicht direkt in cn=config.

Nach dem jetzt der OpenLDAP-Server den Passwordhash kennt, soll jetzt als erstes das Passwort des rootdn umgestellt werden. Durch die Umstellung des Passworts des rootdn können Sie auch gleich testen, ob die Authentifizierung mittels eines Argon2-Passworts funktioniert. Das folgende Listing zeigt die Änderung des Passworts:

dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: {ARGON2}$argon2i$v=19$m=4096,t=3,p=

1$MTIzNDU2Nzg5$t0cMsY/yM7a2wxx

btHWiTtEso2cW2iKrsOHvVCa0+A

Aber warum jetzt Argon2 und nicht mehr SSHA oder PBKDF2 als Passwordhash? Bei diesen Passwordhashes kann, mit relativ preiswerter Hardware ein Brute-Force Angriff auf die Passwörter durchgeführt werden. Oft werden hierfür Grafikprozessoren benutzt. Was dieser preiswerten und schnellen Hardware aber fehlt, ist Arbeitsspeicher. Da kommt dann Argon2 ins Spiel, denn Argon2 erzeugt große Vektoren im Arbeitsspeicher, wie viel Speicher dafür benötigt wird, kann beim erzeugen des Passworts festgelegt werden. Mehr zu Argon2 gibt es hier. Zu beschreiben, wie jetzt welche Parameter beim erzeugen eines Passworts gesetzt werden sollten, würde den Rahmen hier sprengen. Ein guter Einstig zu dem Thema finden Sie hier.

Das Passwort für den rootdn wurde von mir mit den Standardwerten von Argon2 erzeugt. Das Passwort habe ich mit dem folgenden Kommando erzeugt:

echo -n „geheim“ | argon2 „123455678“ -e

Das Passwort ist später „geheim“, „12345678“ ist der salt-Wert für den Passwordhash.

Jetzt können Sie, mittels „ldapsearch -x -D cn=admin,dc=example,dc=net -W -LLL“ den LDAP-Baum abfragen. Wenn das klappt, funktioniert auch der Passwordhash in Argon2.

Um die Passwörter in Argons2 und später auch TOTP testen zu können, habe ich eine OU „ou=users,dc=example,dc=net“ angelegt in der alle neuen Benutzer abgelegt werden. Den ersten Benutzer sehen Sie in der folgenden LDIF-Datei:

dn: cn=u1,ou=users,dc=example,dc=net
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
loginShell: /bin/bash
homeDirectory: /home/u1
uid: u1
uidNumber: 10010
gidNumber: 10000
sn: u
givenName: 1
userPassword: {ARGON2}$argon2i$v=19$m=4096,t=3,p=

1$MTIzNDU2Nzg5$t0cMJsY/yM7a2w

xxbtHWiTtEso2cW2iKrsOHvVCa0+A
cn: u1

Nach dem Anlegen des Benutzers können sie auch hier wieder mit ldapsearch testen, ob eine Authentifizierung mit dem Argon2-Passwort möglich ist. Damit ist der erste Schritt zur zwei-Faktoren-Authentifizierung mit sicherem Passwort schon abgeschlossen.

Jetzt kommt der zweite Teil, Einrichten von TOTP mit dem neuen OpenLDAP-Modul otp.la. Das Modul muss als erstes geladen werden, dafür sehen Sie hier die folgenden LDIF-Datei:

dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: {2}otp.la

Jetzt tragen Sie noch mittels einer LDIF-Datei das Overlay in die Objektdatenbank ein:

dn: olcOverlay=otp,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig

Achten Sie bei der Nummerierung der Datenbank auf Ihre Konfiguration.

Die manpage zu slapo-otp beschreibt zwar alle Parameter die benötigt werden genau, aber wie jetzt welcher Parameter zu setzen ist, fehlt ganz. Was sagen Entwickler dazu? „Wieso Dokumentation, steht doch alles im Quellcode!“ Im folgenden Listing sehen Sie die Konfiguration für TOTP:

dn: ou=users,dc=example,dc=net
changetype: modify
add: objectClass
objectClass: oathTOTPParams

add: oathOTPLength
oathOTPLength: 6

add: oathHMACAlgorithm
# choose SHA1, algorithm OIDs are specified in RFC 8018
oathHMACAlgorithm: 1.2.840.113549.2.7

add: oathTOTPTimeStepPeriod
oathTOTPTimeStepPeriod: 30

add: oathTOTPTimeStepWindow
oathTOTPTimeStepWindow: 3

Hier werden für die OU ou=users,dc=example,dc=net drei Parameter gesetzt:
– oathOTPLength: 6 (Die Länge des OTP-Tokens für den zweiten Faktor)
– oathHMACAlgorithm: 1.2.840.113549.2.7 (Der ODI für den Verschlüsselungsalgorithmus)
– oathTOTPTimeStepPeriod: 30 (Die Dauer der Gültigkeit des Tokens)
– oathTOTPTimeStepWindow: 3 (maximales Gültigkeitsfenster hier 3*30 Sekunden)

Dieses sind die Standardwerte, die auch vom Googleauthenticator und freeOTP+ genutzt werden.

Die Parameter werden immer eine OU zugewiesen und könne anschließend an die Benutzer übergeben werden.

Jetzt wird ein sharedkey für die Errechnung des Tokens benötigt, die folgenden Kommandos erstellen eine Datei mit einem sharedkey im data-Format:

  • $ touch sharedkey
    $ chmod 600 sharedkey
    $ openssl rand 20 > sharedkey
    $ base32 sharedkey
    7XNAA3KOAFGUTBSPWUGTNC6OSKMRKANW

Das Ergebnis ist der Schlüssel der in die entsprechende App, z.B. Googleauthenticator, eingetragen werden muss, aus der dann der sechs-Stellige Token generiert wird.

Jetzt fehlt nur noch die Anpassung des Benutzers. Dazu erzeugen Sie eine LDIF-Datei mit dem folgenden Inhalt:

dn: cn=u1,ou=users,dc=example,dc=net
changetype: modify
add: objectClass
objectClass: oathTOTPToken

add: oathTOTPParams
oathTOTPParams: ou=users,dc=example,dc=net

add: oathSecret
oathSecret:< file:///root/sharedkey

add: objectClass
objectClass: oathTOTPUser

add: oathTOTPToken
oathTOTPToken: cn=u1,ou=users,dc=example,dc=net

Damit wird das Benutzerobjekt um die benötigten Parameter erweitert. Damit der Benutzer den Schlüssel nicht von Hand in die App eintragen muss, kann aus dem Schlüssel ein QR-Code erzeugt werden, der dann einfach mit der App gescanned werden kann.

Ist der Schlüssel eingetragen, kann der erste Test mit dem Benutzer durchgeführt werden. Einfach ein:

ldapsearch -x -D cn=u1,ou=users,dc=example,dc=net“ -W -LLL

Ausführen. Bei der Fragen nach dem Passwort geben Sie als erstes das Passwort ein, unmittelbar im Anschluss den sechs-Stelligen Token, z.B „geheim123456“ Ohne Leer- oder Trennzeichen.

Das war es dann schon, jetzt können Sie nach und nach alle Benutzer auf eine zwei-Faktoren-Authentifizierung umstellen.

Damit die Anwender nicht den Schlüssel in die App eintragen müssen, ist es sinnvoll einen QR-Code aus dem Schlüssel zu erstellen, der dann eingescanned werden kann. Dazu wird das Programm qrencode benötigt. Erst wird der Text für den QR-Code erstellt und anschließend der QR-Code.

QR=“otpauth://totp/ldap:u1@example.net?secret=7XNAA3KOAFGUTBSPWUGTNC6OSKMRKANW&issuer=stka&30&digits=6&algorithm=SHA1″
echo $QR | qrencode -s9 -o u1@example.net.png

Selbstverständlich können Sie den Text für den QR-Code auch direkt an das Programm übergeben.

Das war der zweite Teil zur zwei-Faktoren-Authentifizierung. Ich denke, ein Teil wird noch kommen. Darin wird es dann wieder darum gehen, dass ganze über Ansible einzurichten.

This entry was posted in LDAP and tagged , , , . Bookmark the permalink.