Wie speichert LDAP die Passwörter? SHA-? welches Salt?

Hi,

wir testen gerade unsere “app” und wir wollen nicht das user-Passwort im Klartext in der App speichern.

Also dachten wir: wir speichern den gehashten String, so wie er im LDAP vorkommt und dann wird beim Login der String mit dem im LDAP verglichen.
Ist das fundamental eine schlechte Idee?
Worst case, dass ich mir ausdenken kann: jemand greift den Hash ab und kann sich als diese Person mit der app ausgeben. Der lauscher kommt dann aber weder an das Passwort, noch kann er an anderer Stelle (schulkonsole, etc) etwas damit anfangen.
In diesem Fall, kann also der app-Server beim erstmaligen login (mit Passwort) den hash zurückgeben und ab dann wird mit dem hash angemeldet.
update:

  • doch noch ein Nachteil: wenn man das Passwort im klartext speichert, dann kann man sich eben gegen LDAP authentifizieren, der web-server der die App bedient kann anonym bleiben (gegenüber LDAP). Wenn man jetzt nur den Hash speichert, dann muss der webserver (z.B. http-basic-auth) so konfiguriert werden, dass der server mit admin-rechten das “userPassword” liest und mit dem angegebenen string vergleicht. Der WEbserver muss also erhöhte Rechte gegenüber LDAP haben. hm… unless man verwendet SASL o.ä. was wiederum lmn 6.2 im LDAP nicht unterstützt (nur: 'DIGEST-MD5', 'NTLM', 'CRAM-MD5', 'LOGIN', 'PLAIN'), oh, damnit, NTLM würde vllt. sogar funktionieren.

Nächste Implementationsstufe wäre ein private-public-key Verfahren, das beim erstmaligen Login (mit Passwort) ausgehandelt wird und ab dann verwendet wird. Nachteile: komplizierter, user-daten extra vorhalten im LDAP/SQL auf serverseite. Dann kann ich auch gleich auf lmn7 und kerberos und tickets warten.

Eigentlich wäre die Sache jetzt erledigt, aber rein aus Interesse hab ich etwas getestet und festgestellt, dass bei einem sophomorix-passwd ein neuer password string mit einem neuen Salt entsteht. Ich kann also nicht von vorneherein wissen, was im LDAP steht, weil das Salt random ist. Ich vemute, das Salt auf immer das gleiche zu setzen ist fundamental eine schlechte Idee, weil man dann auch gleich ohne Salt speichern könnte.

VG, Tobias

Fazit: Was ich so von amazon, adobe usw. leaks gehört habe, ist die lmn ziemlich sicher: mit random salt gehashte Passwörter werden gespeichert und nichts anderes. gut, oder?

Für die, die es näher interessiert, hier wie ich mich rangetastet habe:

  1. Im LDAP stehen solche strings:
    {SSHA}2bWb02+pfnAno5TQtTjDfH3fzgBzVVIwUlNERXRWOGJBS0JiYlBQMDIyMlZpZ1ZsOHkxaA==

  2. Das sind (ohne das “{SSHA}”) 78 zeichen. Das ist base64 encoded (alles nach “{SSHA}”). Die dekodierte Variante sieht nicht zwangsläufig hier gut aus, mein pythonskript liefert mir:
    b"\xd9\xb5\x9b\xd3o\xa9~p'\xa3\x94\xd0\xb58\xc3|}\xdf\xce\x00sUR0RSDEtV8bAKBbbPP0222VigVl8y1h"

  3. Die ersten 20 Zeichen gehören zum SHA1-Hash, die restlichen Zeichen sind das/der Salt.
    salt: b'sUR0RSDEtV8bAKBbbPP0222VigVl8y1h'

  4. Jetzt kann ich reverse testen, ob das richtige Password plus salt mit dem sha1-Algorithmus den gleichen Hash ergibt:
    sha1(123456) = b"\xd9\xb5\x9b\xd3o\xa9~p'\xa3\x94\xd0\xb58\xc3|}\xdf\xce\x00"

Juhu, mein Test stimmt scheinbar: 1. es wird tatsächlich sha1 verwendet, 2. die Zusammensetzung mit den 20 bytes funktioniert, 3. das salt habe ich auch.
Die relevanten python befehle dazu:

from ldap3 import Server, Connection, ALL
server = Server('meineschule.org', "cn=admin,dc=meineschule,dc=org", "passwort von ldap-admin", port = 636, use_ssl = True, get_info=ALL)
conn.bind()

conn.search('dc=humboldt-gymnasium,dc=ka,dc=schule-bw,dc=de', '(uid=testschueler)', attributes=['userPassword'])
pw_string=str(conn.entries[0]["userPassword"])[2:][:-1]
print(str(len(pw_string)) + ": " + pw_string)

import base64
code_b64decode = base64.b64decode(pw_string)
print(code_b64decode)

hashstring = code_b64decode[:20]
salt = code_b64decode[20:]
print("salt: " + str(salt))

orig=b'123456'
import hashlib                                                                                                       
sha = hashlib.sha1(orig)
sha.update(salt)
print("sha1(123456) = " + str(sha.digest()))

Programm führt man mehrmals aus, dazwischen ein sophomorix-passwd -u testschueler --password 123456 und man sieht, dass die salt sich ändern und das verschlüsselte Passwort.

Weblinks der Vollständigkeit halber, diebesonders hilfreich waren: