PHP Weiterleitung nach "DB-Check"

Ich möchte das Passwort, welches bei der Registrierung eingegeben wird in meine DB abspeichern, und zwar in md5.
Soweit geht das auch mit folgendem Code:


PHP:
//...
$password = md5($password);
//...

In der DB wird das auch gehashed angezeigt, funkt ja soweit. Das Einloggen macht mir aber jetzt Probleme, ich denke mal er vergleicht das eingegebene Passwort in der Loginform im Klartext mit dem Passwort in md5 und diese sind ja nicht gleich.

Habe folgenden Code in der login.php:

PHP:
<?php

session_start();

$username = $_POST["username"];
$password = md5($_POST["password"]);

$connection = mysql_connect("localhost", "root", "") or die ("Verbindung zur Datenbank fehlgeschlagen");
mysql_select_db("login") or die ("Konnte Datenbank nicht oeffnen");

$abfrage = "SELECT username, password FROM user WHERE username LIKE '$username'"; //vllt noch 'LIMIT 1'
$ergebnis = mysql_query($abfrage);

$row = mysql_fetch_object($ergebnis);

if($row -> password == $password)
{
	$_SESSION["username"] = $username;
	echo "Login erfolgreich. <a href='member.php'>Member Area</a>";
}else
{
	echo "Benutzername und/oder Passwort waren falsch. <a href='index.php'>Zurueck</a>";
}

?>

Es kommt immer "Benutzername und/oder Passwort waren falsch.".

Woran liegt das?

Guten Abend.
 
OK, mal Stück für Stück zerpflückt:

PHP:
$username = $_POST["username"];
...
$abfrage = "SELECT username, password FROM user WHERE username LIKE '$username'"
Das schreit geradezu nach einer SQL Injection. NIE darfst du einer POST- oder GET-Variable trauen und sie ungefiltert in einen Query schicken. Verwende dafür IMMER mindestens mysql_real_escape_string(). Ansonsten endest du wie Sony.

PHP:
$password = md5($password);
Ist hochgradig unsicher. Sollte jemand deine Datenbank in die Finger bekommen (z.B. über obige Injection-Lücke) kann er hier einfach eine Rainbow Table einsetzen, um innerhalb von bestenfalls ein paar Stunden all deine Passwörter in Klartext zu verwandeln.
Verwende immer ein Salt für deine Hashes, ansonsten wird dein Hash per Rainbow Table ratzfatz zerpflückt.

Das könnte z.B. so aussehen:
Irgendwo in einer Config-Datei (z.B. da, wo du auch deine DB-Login - Daten hinterlegst) steht sinngemäß
$salt = fhafkjaffgj43urejf34hfg hfhfghfgdfg dfdf54654 rt jztz$%&%4645fdg;
Statt jetzt $password = md5($input_password); zu machen, machst du statt dessen z.B. $password = md5($salt.$input_password);. Solche Kleinigkeiten erhöhen die Sicherheit enorm. Besser sind natürlich Lösungen mit Salt+Pepper, wo 2 unabhängige Werte zusammen mit dem Klartext-PW in den Hash einfließen, z.B. wo jedem User-Eintrag in der DB ein Pepper zugewiesen wird und global ein Salt.


Was deinen Vergleich angeht: Sieht gar nich so falsch aus. Evtl. hast du Leerzeichen oder so n Schmonz in einem der beiden Werte rumschwirren. Schick den Kram, bevor du ihn beim speichern hashst, doch durch trim(), evtl mit erweiterten Parametern (entferne Zeilenumbrüche, Tabs,...). Wenn du jetzt vor dem Vergleich deine Eingabe genau so trim()-st kannst du das schonmal als Fehlerquelle ausschließen.
 
Ne habe ich nicht, dass sehe ich ja schon daran, das in der DB der Hash-Wert ohne Leerzeichen ist und das PW, welches ich eingebe, auch ohne Leerzeichen. Ohne md5 werde ich problemlos eingeloggt...

Komisches Ding.

EDIT:

Problem gelöst! Ich habe in der DB der Spalte "password" eine Länge von 30 Zeichen zugewiesen, das md5 Passwort hat aber 32 Zeichen und somit haben die 2 Zeichen gefehlt, autsch! :)

D.h. ich sollte als Länge immmer >32 angeben oder was (wenn ich md5 hashe)?

Gruß
 
Zuletzt bearbeitet:
@Daaron: MD5 ist sowieso nicht mehr sicher. Da hilft dir auch Pfeffer und Salz nicht wirklich. Es gibt nicht umsonst spezielle Hash-Verfahren für Passwörter, die auch noch extra langsam sind.

Anscheinend bekommt PHP 5.5 eine bessere API für sowas. Wird auch Zeit.

http://www.golem.de/news/php-5-5-sichere-passwoerter-mit-neuem-crypt-api-1209-94534.html

Edit: Die PHP-RFC für die Password Hashing API ist klasse:
As recent attacks have shown, strong password hashing is something that the vast majority of PHP developers don't understand, or don't think is worth the effort.
 
Zuletzt bearbeitet:
PHP 5.5 ist für die nächsten paar Jahre keine Diskussion wert. PHP 5.4 ist jetzt seit ein paar Monaten draußen, trotzdem isses in keiner der großen Server-Distributionen enthalten. Der nächste Kandidat könnte Debian 7 werden, keine Ahnung ob da in den Repos wenigstens 5.4 vorgesehen ist.

Das einzige, was md5 mit Salt/Pepper unsicherer als sha1 macht ist die Tatsache, dass für md5 bereits Kollisionen nachgewiesen wurden. Es stellt ja zum Glück keinen programmiererischen Mehraufwand dar, sha1($hashmich) statt md5($hashmich) aufzurufen.
 
Also sollte ich lieber sha1 nutzen anstatt md5 und dieses dann salten & peppern?

Gruß
 
SHA-1 ist genauso geeignet bzw. ungeeignet wie MD5. http://www.php.net/manual/en/faq.passwords.php#faq.passwords.fasthash

Man sollte lieber gleich PBKDF2 oder bcrypt nehmen. Die PHP-Leute empfehlen auch noch Blowfish. Das kann man mit crypt() machen oder gleich auf die PHP-5.5-Kompatibilitätslösung password_compat zurückgreifen. Im Golem-Artikel ist die sogar erwähnt und verlinkt (letzter Absatz).

In der RFC steht auch noch was dazu: https://wiki.php.net/rfc/password_hash

Ob Pfeffer wirklich was bringt, ist sowieso umstritten. Einfach mal Googlen. Salz ist immer nötig, aber hilft auch "nur" gegen besagte Rainbow Tables.
 
Zuletzt bearbeitet:
character schrieb:
Gegen Brute Force vom Frontend aus kann man sich ganz leicht schützen, indem man einen Temporary Ban - Mechanismus implementiert.
Brute Force auf den bereits aus der Datenbank geangelten Hash halte ich für kein sehr großes Problem, denn das läuft effektiv auf eine Rainbow Table hinaus, die nicht die gesalzenen Passwörter finden will. Eine RT für n Passwort, dass mit nem 1024-stelligen Salt kombiniert wurde, kannst du unter Ulk verbuchen, die ist wirtschaftlich nicht machbar. Das dürfte in den Bereich mehrerer Exabyte gehen.
 
Ich glaube du unterschätzt wie gut Brute Force heutzutage aufgrund der abartigen Leistung von Grafikkarten gegen die "simplen" Hashes funktioniert (natürlich nur offline). Ich denke auch nicht, dass die Länge des Salts eine siginifikante Rolle bei der Sicherheit spielt.

Allerdings bin ich kein Kryptoexperte und verlasse mich da hauptsächlich auf andere, die sich damit (im Gegensatz zu mir) gerne beschäftigen. Better safe than sorry.

Die meisten Probleme entstehen heutzutage ohnehin durch Social Engineering. Gegen die Dummheit der User kann man einfach nichts machen, siehe gerade wieder aktuell bei Guild Wars 2.
 
character schrieb:
Ich glaube du unterschätzt wie gut Brute Force heutzutage aufgrund der abartigen Leistung von Grafikkarten gegen die "simplen" Hashes funktioniert (natürlich nur offline).

IGHASHGPU: 5,5 Mrd MD5 und 2,3 Mrd SHA1 Hashes pro Sekunde, um genau zu sein.
Und wie lang der Salt ist, ist dann auch vollkommen irrelevant. Wenn man dem Tool einen festen Salt mitteilen kann, dann stören den auch keine 1024 Zeichen Salts.
 
Zurück
Oben