Christian Seiler: Passwörter unlesbar machen

Beitrag lesen

Hallo Yeti,

zur Zeit stehe ich vor der Aufgabe, die bisher mit MD5 gehashten Passwörter einer Datenbank sicherer zu machen.

Sicherer wovor?

MD5 und SHA-1 sind ja bereits geknackt

Nein, bitte keine Panikmache!

MD5 ist insofern "geknackt", als dass es möglich ist, zwei Nachrichten zu erzeugen, die den gleichen Hash haben. Es gibt allerdings bis heute noch keinen Algorithmus außer Brute-Force, der Dir eine Klartextnachricht zu einem bereits vorhandenem Hash liefert. Es ist zwar möglich (und vmtl. auch wahrscheinlich), dass sich dies in den nächsten Jahren ändern wird, aber noch kannst Du MD5 nicht einfach ohne weiteres "rückgängig machen".

Dennoch ist es natürlich sinnvoll, für neu entworfene Anwendungen nicht mehr auf MD5 zu setzen, da die Sicherheit des Algorithmus durchaus kompromittiert ist.

SHA-1 ist nicht geknackt. Es gibt zwar aus gutem Grund einige Zweifel an der Sicherheit von SHA-1, da es bereits ein Verfahren gibt, der Brute-Force auf eine deutlich geringere Anzahl an Versuchen reduziert, allerdings ist diese Anzahl immer noch groß genug, um Brute Force nicht praktikabel zu machen.

Daher wäre für mich SHA-1 der Algorithmus meiner Wahl, wenn ich Passwörter in Datenbanken hashen wollte. Er wird sich vielleicht in Zukunft als unsicher herausstellen, da Passwörter aber eine begrenzte Lebensdauer haben (oder zumindest haben sollten!), stellt das in meinen Augen kein wirkliches Problem dar.

Wobei ich selbst mit MD5 kein Problem hätte, wenn es sich um Passwörter handelt, die sowieso unverschlüsselt über das Internet übertragen werden, denn da ist es viel Wahrscheinlicher, jemand fängt die auf dem Weg ab, als dass jemand in Deinen Server einbricht, sich ein komplettes DB-Dump zieht und dann alle Passwörter knackt.

Wenn ich eine Anwendung entwerfen wollte, die Hashes für andere Zwecke, z.B. für digitale Signaturen, benötigt, würde ich natürlich nicht mehr SHA-1 nehmen. SHA-256 oder SHA-512 wären zum Beispiel denkbar. Oder RIPMED-160. Diese sollten auf absehbare Zeit ausreichende Sicherheit bieten können.

und zu MD5 habe ich auch schon Internetseiten gefunden, wo ich die halbe Datenbank sofort knacken und den Rest in Auftrag geben konnte.

Diese Seiten nutzen vermutlich sogenannte Rainbow-Tabellen, d.h. vorberechnete MD5-Hashes zu allen möglichen Passwörtern bis zu einer gewissen Länge.

Gegen so ein Verfahren hilft das sogenannte "Salting": Ein Passwort wird vor dem Hashing mit einem Zufallsschlüssel konkateniert und der Zufallsschlüssel wird auch mit abgespeichert, d.h. so:

Gehashtes Passwort = Salt + Hash(Salt + Passwort)

Wenn der Salt z.B. aus 6 Zeichen bestünde, dann kann könnte man das Passwort über folgenden Algorithmus überprüfen:

Salt = Erste 6 Zeichen von gespeichertem Passwort
TestPasswort = Salt + Hash(Salt + Eingegebenes Passwort)
Vergleiche TestPasswort mit gespeichertem Passwort

Wenn für jedes neu festgelegte Passwort eine andere Zufallszeichenkette als Salt genutzt wird, dürfte man Rainbow-Tabellen so ziemlich gut aushebeln können - da dann für genau dieses Salt jemand selbst nochmal Rainbow-Tabellen berechnen müsste, und damit wären wir wieder bei Brute Force.

Das Verfahren hilft auch prima gegen diese MD5-Knackdienste, selbst wenn man weiterhin MD5 verwendet.

Ich persönlich mag die PHP-Funktion crypt,

Crypt nutzt entweder einen 3DES-basierten Hash, der maximal 8 Zeichen schluckt (dafür aber gar keine Kollisionen besitzt, da die Eingabedaten begrenzt sind) oder selbst MD5 oder SHA1 (dann fangen die Passwörter mit $1$ oder $2$ an, $1$ für MD5, $2$ für SHA1). Der einzige Vorteil von crypt() ist, dass es von vorne herein Salts verwendet. Da 3DES-crypt unter Windows nicht zur Verfügung stht, kann crypt unter Windows selbst nur MD5 und SHA1.

allerdings soll hier der MySQL-Server aus Sicherheitsgründen die Funktionen ausführen.

Was für Sicherheitsgründe? Wäre es nicht sinnvoller, das Passwort nicht nochmal unverschlüsselt über die Leitung zu jagen zwischen MySQL und PHP? Mir ist nicht klar, warum das die Sicherheit erhöhen sollte...

Wie kann ich das Dilemma lösen?

Baue Salting ein und nutze als Algorithmus weiterhin MD5 oder SHA1. Du musst Dir halt nur überlegen, wie an einen möglichst geeigneten zufälligen Salt herankommst.

Viele Grüße,
Christian