Donnerstag, 16. Oktober 2008

About MD5 Passwords [GERMAN]

Mich fragte jemand auf ragezone, wieso man mit md5 "verschlüsselte" Passwörter nicht wieder entschlüsseln kann. Dies liegt daran, dass md5 eine Einwegfunktion ist, d.h. eine Funktion, die sich nicht umkehren lässt. Es gibt unendlich viele Funktionsargumente, aber nur eine beschränkte (wenn auch sehr große) Anzahl an Funktionswerten bzw. Bildern. md5 verschlüsselt nämlich nicht, er bildet nur eine Prüfsumme.

Klingt vielleicht auf den ersten Blick verwirrend, ist aber eigentlich ganz einfach. Ich versuche im Folgenden, den Sachverhalt mit einem Beispiel zu verdeutlichen. (Mit der Thematik Vertraute finden sicherlich einige Dinge, die im Detail nicht ganz stimmen; für einen ersten Einstieg in die Materie halte ich es jedoch für verschmerzbar, wenn gewisse Details nicht 100%ig auf den realen Fall übertragbar sind.)

Man stelle sich vor, seine Bankkarten-PIN laute 4711 (entspricht dem Passwort eines Benutzers). Damit sich diese bei der Übertragung vom Geldautomat (entspricht dem Eingabeformular im Browser) zum zentralen Bankserver (entspricht dem Server einer Internetseite) nicht abfängen lässt, wird eine md5-Ähnliche Funktion auf die PIN angewandt, beispielsweise quersumme(4711) = 13. Der zentrale Server überprüft nun, ob die übertragene 13 gleich der Quersumme der gespeicherten PIN 4711 ist.

Wenn nun ein böser Bub die Übertragung anzapft und die Prüfsumme 13 abfängt, so ist es ihm möglich, diese Prüfesumme zu verwenden, um an diesem Automaten Geld abzuheben. Es ist ihm jedoch nicht möglich, daraus auf die geheime PIN zu schließen. Diese kann nämlich nicht nur 4711, sondern bspw. auch 9400 oder 1237 lauten. Es ist nicht möglich, aus der Quersumme auf die ursprüngliche Zahl zu schließen!

Ähnlich verhält es sich auch beim md5-Algorithmus, einmal angewandt kann die Eingabe nicht wieder entschlüsselt werden.

Es ist jedoch möglich, md5 zu knacken, bspw. mittels Brute-Force-Angriffs. Dies bedeutet, dass alle möglichen Eingaben durchprobiert werden, bis man Erfolg hat. Man erhält dadurch (nach einer unter Umständen sehr langen Zeit) ein Argument, für das md5 den selben Funktionswert zurück gibt wie beim "korrekten" Passwort. Abhängen vom gewählten Passwort ist die Chance mehr oder weniger klein, dass es sich dabei um das ursprüngliche Passwort handeln. Ohne weitere Informationen (bspw. Kontext-Informationen) ist es jedoch nicht möglich festzustellen, ob das erhaltende Argument tatsächlich das Passwort des Nutzers ist.

Mit einem kleinen Trick kann man die Sicherheit von md5 oder anderer Hashing-Algorithmen wie SHA-1 jedoch erhöhen: mit sogenannten Salts. Dies ist ein für jede Anwendung spezifischer Wert, der zusätzlich zum Argument übergeben wird. Dadurch ist es einem Angreifer, selbst wenn er einen Hash (Funktionswert) oder gar ein mögliches Argument besitzt, nicht möglich, auf mehr als eine Seite zuzugreifen.

Auf mein obiges Beispiels von Geldautomaten bezogen: Stellen wir uns vor, wir haben zwei Geldautomaten, Automat 1 und Automat 2 mit jeweils passendem Server dazu. Gebe ich meine PIN an Automat 1 ein, so berechnet dieser nicht quersumme(PIN), sondern quersumme(PIN+1); Automat 2 analog dazu quersumme(PIN+2). Lautet die PIN 4711, so berechnet Automat 1 quersumme(4712) = 14. Der böse Bub fängt nun die übertragene 14 ab und schließt, den quersumme-Algorithmus vor Augen, auf eine mögliche PIN 1238. Mit dieser versucht er nun, bei Automat 2 Geld abzuheben was jedoch scheitert, denn quersumme(1238+2) = 7, jedoch quersumme(4711+2) = 15. Der Angreifer muss nun also nicht nur Automat 1 belauschen, sondern zusätzlich rausfinden, welchen Salt Automat 1 verwendet, anschließend Automat 2 belauschen, dessen Salt herausfinden und anschließend versuchen, die gesammelten Ergebnisse so zu verwursten, dass er gültige PINs für die Automaten berechnen kann.

Während dies bei der Quersumme noch relativ einfach möglich ist wird es mit zunehmender Komplexität der Algorithmen immer schwieriger.

Je nach Anwendungsfall reicht md5, besser jedoch md5+Salt. Wer mehr Sicherheit benötigt, sollte SHA-1(+Salt) verwenden oder weitere Stufen, bspw. SHA-256(+Salt).