Hallo,
Original von NeonZero
Diese Wahrscheinlichkeit ist nicht gering. _Sollte_ eine Brute Force Attacke (ohne Wörterbuch!) ein gültiges Passwort finden, so ist es sogar sehr wahrscheinlich, dass es sich um ein vollkommen kryptisches Passwort handelt, was von dem tatsächlich vergebenen Passwort meilenweit entfernt ist.
Dies ist so leider nicht richtig.
Wenn man einen Brute-Force angriff startet, so schrenkt man die Anzahl der zuverwendenen Zeichen ein, oft auf a-z und 0-9 (ggf. noch Großbuchstaben).
Des Weiteren fängt man mit kruzen Eingaben an, also erst 1 Zeichen, dann 2 Zeichen bis hin z.B. 8 Zeichen.
Denn keiner wird als Eingabe alle 256 möglichen Werte für ein Byte/Zeichen verwenden, sondern dieses immer einschränken, auf 36 oder ggf. 62 Variationen pro Zeichen, sonst würde das Finden einer Kollision viel zu lange dauern.
Des weiteren werden die meisten User wohl kaum ein 0x00-Byte, einen Backspace o.ä. in ihrem Passwort verwenden.
Original von lookshe
? wenn du ein sicheres Passwort mit Sonderzeichen, Groß- und Kleinschreibung etc. verwendest, bist du ziemlich auf der sicheren Seite.
Ich würde diese Aussage so schon unterstützen, denn dass man eine Kollision findet, mit H(PW) = H(PW') und PW != PW' ist so gerring, dass man diese vernachlässigen kann.
Was man also meistens findet, ist das orginal Passwort und keine Kollision die die oben genannten Bedingungen erfüllen.
Verwende ich Klein- & Großbuchstaben, Zahlen und hab eine Passwortlänge von 10 Zeichen, so gibts immerhin über 10^17 Kombinationen. Hab ich 100 Rechner mit 100 Mio. Versuchen/Sek, dauerts immerhin noch gute 2 1/2 Jahre um alle Kombinationen auszuprobieren.
Und eine beliebige Kollision bei einem sicheren Hashverfahren zu finden ist nicht so einfach. Aufgrund des Geburtstagsparadoxon muss ich im Schnitt nur 2^(n/2) (n: Bitlänge des Hashs) Hashwerte erstellen, was bei MD5 z.B. ca. 2^64 Hashwerte wären.
Im März 2004 startete ein Projekt (MD5CRK), welches eine beliebige Kollision in MD5 finden sollte. Um eine Kollision in ~3 Wochen finden zu können, benötigt man rund 6000 Rechner mit 2 Gigaflops Prozessoren.
Allerdings hat man dann nur eine beliebige Kollision gefunden.
Um eine Kollision zu finden, für einen vorgegebenen Hashwert x, muss man im Schnitt (2^n)/2 bzw. 2^(n-1) also bei MD5 2^127 Hashwerte berechnen.
Dies ist ein 10^18 mal so großer Aufwand, mit den 6000 Prozessoren würde man nicht mehr 3 Wochen, sondern 3*10^18 Wochen (oder 60 Billiarden Jahre) brauchen.
Eine Kollsion mit H(PW) = H(PW') und PW != PW', mit gegebenem H(PW) zu finden, ist so gut wie unmöglich, sofern der Hash-Algorithmus stark kollisionsresistent ist, was MD5 und SHA1 zur Zeit noch sind.
Verwende ich also ein Passwort, welches aus einer groß Menge stammt, z.B. 12 Zeichen lang und 62 Zeichen zur Auswahl, ist auch fast unmöglich, dieses Passwort zu finden.
Und klar kann ich beim ersten Testen eine Kollision per Glück finden (mit den oben genannten Bedingungen), aber es ist 600 mal wahrscheinlicher, dass beim Lotto fünf mal nacheinander die gleichen Zahlen gezogen werden.
Natürlich immer vorrausgesetzt, die Hashfunktion ist Kollisionsresitent, was die Quersumme z.B. ja nicht ist.
PS: MD5CRK wurde ~5 Monaten eingestellt, weil ein chinesisches Wissenschaftlerteam die erste Kollision in der vollständigen MD5-Funktion gezeigt haben, wobei sie aber kein Bruteforce verwenden haben, sondern analytische Methoden (seit dem gilt MD5 nicht mehr als schwach Kollisions sicher).
Für spezielle Kollisionen mit vorgegebenem Hashwert kann man diese Methode aber nicht verwenden, wo Brute Force die schnellste Attacke bleibt.
@Sic!:
Eine Verschlüsselung zu verwenden bringt mehr Nachteile als Vorteile.
Wie du gesehen hast, ist eine Kollision für dein Passworthash sooooo unwahrscheinlich, dass man es vernachlässigen kann.
Verwendet man einen Verschlüsselungsalgorithmus wie z.B. AES, so hat man das Problem, wo bewahrt man sicher den Key für den Algorithmus auf?
Denn wenn jmd. in deinem Server einbricht, und die User-Tabelle kopiert, so hat er dann oft auch Zugriff auf den Key für den Algorithmus, und kann bequem alle Passwörter der User entschlüsseln.
Wenn die als Hashwerte hinterlegt sind, muss der Angreifer erst eine Wörterbuch/Rainbow/Brute Force Attacke starten, und bei guten Passwörter wird dies mit einer Wahrscheinlichkeit von 99,99999[...]99% nicht zum Ziel führen.
Des Weiteren gibts ja auch böse Admins, die sich für die Passwörter der User intressieren. Die rufen dann die User-Tabelle auf, verwenden den Key und entschlüsseln das Passwort. Bei einem Hashwert ist dies so nicht möglich.
Dann gibts noch das Problem des Backups. Wenn ich die Passwörter per AES verschlüssel und ein Backup der Usertabelle mache, wäre es sinnvoll, auch den AES Schlüssel zu sichern, denn wenn die Festplatte mal den Geist aufgibt => AES Schlüssel weg => User Passwörter weg.
Also muss ich den AES Schlüssel irgendwie sichern.
Bei einem Hashverfahren gibts das Problem nicht.
Auch kann ich so leichter die Passwörter portieren. Hat man z.B. ein Board, und möchte dass die User-Acc auch für das CMS gilt, welches aus einem fremden Server liegt, so kann ich die Hashwerte einfach rüberkopieren.
Ein anderes Problem ist bei Anwendungen, die geheime Werte kaum schützen können, wie z.B. PHP Scripts.
Würde das WBB z.B. AES anstatt MD5 verwenden, müsste der Key irgendwie in einer PHP Datei hinterlegt sein, damit man keinen Root-Server benötigt um ein wBB zum Laufen zu bringen.
Das führt zum Problem, dass der AES Key _offen_ im PHP Script hinterlegt ist, und jmd. der deinen FTP Acc. klaut, oder irgendwie sonst Dateien am Server auslesen kann, kann nun den AES Key auslesen.
Wie du siehst, führt Verschlüsselung nicht zum Ziel, und vor Panikmache vor Kollisionen rate ich ab, denn diese sind so unwahrscheinlich...
Verwendet man dann z.B. SHA1 statt MD5, ist eine Kollsion noch 4 Milliarden mal unwahrscheinlicher...
Um seine User aber vor schlechten Passwörtern zu schützen, sollte man eine Salt verwenden (verhindert Rainbow-Attacken) sowie evt. über den Einsatz eines
HMAC Gedanken machen.
In PHP ist HMAC sehr schnell realisiert:
$hash = sha1("secret_key".$user_password);
Wobei "secret_key" dann selber natürlich kein "schlechtes" Passwort sein darf.