PHP, MySQL: Session Login mit PDO

...komplette Frage anzeigen

2 Antworten

Dein Hauptproblem ist, dass du keine SQL-Syntaxfehler abfängst, also z.B. if ( $sql ) ... else print_r( $g_dbh->errorInfo());

In deinem Fall muss es LIKE '$username' (mit Quotes) heissen (in der Hoffnung, dass in $username keine ' vorkommen, aber du hast es ja über die :Platzhalter richtig gelöst.

Gruß, Max.

shinigami0815 09.07.2014, 10:41

Ich hab jetzt mal noch was Weiteres gemacht, Passwort Hashing. Hab das Passwort folgendermaßen gehashed:

define("MAX_LENGTH", 6);

function generateHashWithSalt($password){
  $intermediateSalt = md5(uniqid(rand(), true));
  $salt = substr($intermediateSalt, 0, MAX_LENGTH);
  return hash("sha256", $password . $salt) . "+" . $salt;
}

Ich habe das gehashte Passwort und den salt in die DB gespeichert (hab in der Tabelle, wo User und PW stehen, einfach noch eine Spalte gemacht mit dem salt). Nun habe ich aber das Problem: Wie hashe ich jetzt das eingegebene Passwort, damit es mit dem gehashten aus der DB verglichen werden kann? Ich müsste ja eigentlich den salt auch aus der DB lesen und beim hashen des PW mitverwenden, damit wieder das gleiche rauskommt. Allerdings weiß ich nicht, wie ich das realisieren soll.

Hatte so was probiert, das funktioniert aber nicht (wie ich auch schon vermutet hatte):

include "dbverbindung.php";

$username = $_POST["username"];
$password = $_POST["password"];

$sql = $db_link->prepare("SELECT `username`, `password`, `salt` FROM `users` WHERE `username` = :username AND `password` = :password");
$sql->execute(array(':username'=>$username, ':password'=>hash("sha256", $password . 'salt')));    

if($sql->rowCount() > 0){
  $_SESSION["username"] = $username;
  include "Weiterleitung_Login.html";
}else{
  include "Weiterleitung_failed.html";
}
0
maximilianus7 10.07.2014, 12:57
@shinigami0815

hui, salziger gehts kaum noch ;-) -- md5(uniqid(rand()...

ok, allzuviel Aufwand mit dem salt würde ich nicht treiben, was erreichst du damit? Um ein gehaschtes Passwort zu knacken muss der Angreifer mit Brute Force vorgehen, unterstützt mit Regenbogentabellen. Warum sollte er das in deinem Falle tun? Programmierst du eine Bank oder ein Webstore?

Egal, du willst das höchste Mass an Sicherheit anbieten. Da der Angreifer das salt nicht kennt, steigen die Möglichkeiten ins Unermessliche. Allerdings würde auch ein salt als feste PHP-Konstante genügen. Um diese herauszufinden, müsste er die Website von Innen her knacken, d.h. die FTP-Verbindung, und damit hat er alles, die PHP source und damit auch die Zugangsdaten zur Datenbank.

Bleibt das Problem mit dem Insiderwissen, was in grösseren Firmen eine Rolle spielt. Das spricht gegen eine feste PHP-Konstante als salt, da diese dann nicht mehr so einfach auszutauschen geht.

Also für jeden user ein individuelles salt in der Datenbank, wie du es ja vorgesehen hast. Dieses salt wird einmalig beim INSERT eines neuen users erzeugt. Ich denke, die Funktion mt_rand (das "bessere" rand) reicht da vollkommen.

Auf keinen Fall gehört das original-Passwort (aus $_POST) in die Datenbank, sondern das gehashte!

Das Verifizieren geht dann so:

Mit userid das gehashte Passwort und den salt SELECTieren, original password mit dem salt hashen und das Ergebnis mit dem gehashten Passwort vergleichen.

$g_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Set Error handling, gehört ins dbverbindung.php

try   // demo wie PDO-Fehler abzufangen sind. 
{
  $sql = $db_link->prepare("SELECT `password`, `salt` FROM `users` WHERE `username` = :username");
  $sql->execute(array(':username'=>$username);    
  $data = $sql->fetch(PDO::FETCH_ASSOC);        
}
catch (PDOException $err) { echo $err->getMessage(); /* nachfolgende Abfrage ergibt ungleich */}

if ( $data['password'] == hash("sha256", $password . $data['salt']) )
{
  ...login accepted...
}
...

Gruß, Max.

1

Edit: Habe es jetzt umgeändert:

http://de.tinypic.com/r/52j3uo/8

Jetzt funktioniert es.

Ps: sry, dass nur als Bild, gutefrage wollte mich nicht weiteren Code posten lassen.

Was möchtest Du wissen?