2010-12-15 5 views
2

Encore une fois à la recherche d'aide avec la sécurité PHP et un système de connexion. Vous vous demandez si je l'ai fait correctement ici. Si je n'étais pas assez précis, veuillez demander, Toute aide est grandement appréciée. J'essaie de créer un système de connexion sécurisé, juste à des fins d'apprentissage. voici le code:Utilisez-vous correctement les instructions PDO et les instructions préparées pour une connexion sécurisée?

require("constants.php"); 
$DBH = new mysqli($dbhost, $dbuser, $dbpass, $dbname); 

function createSalt() { 
    $length = mt_rand(64, 128); 
    $salt = ''; 
    for ($i = 0; $i < $length; $i++) { 
     $salt .= chr(mt_rand(33, 255)); 
    } 
    return $salt; 
} 
//Salt function created by ircmaxell 

function registerNewUser() { 
    //Check to see if  Username Is In Use// 
    $q = $DBH->prepare("SELECT id FROM users WHERE username = ?"); 
    $username = filter_var($username, FILTER_SANITIZE_STRING); 
    $data = array($username); 
    $q->execute($data); 
    $row = $q->fetch(); 

    if ($row === false) { 
     //If Username Is Not Already In Use Insert Data// 
     $hash = hash('sha256', $pass); 
     $salt = createSalt(); 
     $hash = hash('sha256', $salt . $hash . $pass); //UPDATED 
     $data = array($username, $hash, $salt); 
     $qInsert = $DBH->prepare(
      "INSERT INTO users (username, password, salt) values (?, ?, ?)" 
     ); 
     $qInsert->execute($data); //Inserts User Data Into Table// 
    } 
} 
+0

Recherche PHP.net, je ne ' t trouve une fonction nommée "canonicalize()" Est-ce une fonction définie par l'utilisateur qui n'est pas incluse dans le code? –

+1

De plus, bind_param() est appelé avec "i" comme variable, mais "i" n'est pas défini dans votre instruction préparée.Vous pouvez simplement passer la variable nom d'utilisateur en tant que tableau de membre unique à l'instruction d'exécution et ignorer le paramètre bind_param(). –

+0

ouais je vois que canonicalize() n'est pas une fonction, je pensais avoir lu que c'était une fonction. Je ne pense pas. merci, quant à la variable, merci pour cela aussi. Je l'édite. Merci pour l'aide! – mcbeav

Répondre

3

Cela semble bon jusqu'à présent. J'ai trois suggestions, cependant:

  1. Choisissez un sel plus
  2. Ne pas stocker le sel et le mot de passe digérer séparément
  3. Si votre connexion de base de données est de ne pas localhost utiliser un connecteur de base de données différente: AOP ne fonctionne pas (encore) en charge les connexions SSL

EDIT: en outre, valider l'entrée d'un client fournit un "nom d'utilisateur". Mais puisque votre exemple de code est juste un extrait je suppose que vous le faites. Quand j'ai dit «ne stockez pas le sel et le mot de passe séparément», je voulais dire incorporer le sel dans le hachage du mot de passe stocké. Puisque l'algorithme de hachage de votre choix produit une chaîne assez longue (64 caractères) composée de [0-9a-f], vous pourriez envisager de générer un sel de longueur aléatoire (crédits à ircmaxell ici) et soit concaténer cela au début ou fin du mot de passe hash. Donc, vous finirez par stocker des valeurs de longueur variable (96 - 128 caractères) la valeur de l'insignifiance (à l'extérieur):

$hash = hash('sha256', $pass); 
$salt = substr(hash('sha256', mt_rand(0, 1337)), mt_rand(0, 31), 32); 
$hash = $salt . hash('sha256', $salt . $hash . $pass); 
+0

Merci! J'apprécie vraiment le commentaire. Je n'étais pas au courant que PDO ne supportait pas SSL. Des suggestions à ce sujet? Merci encore pour votre aide. – mcbeav

+0

En outre, je suis inquiet au sujet de la performance. Je ne sais pas trop ici, mais est-ce que j'utilise peut-être trop de variables? – mcbeav

+1

En ce qui concerne le support des instructions préparées (qui est un * Good Thing *), j'utilise l'extension mysqli de PHP. En ce qui concerne les variables: je suis personnellement un fan de code lisible. Donc non. Il vaut mieux être capable de * lire * le code au lieu d'avoir à le déchiffrer, car vous accédez à $ _POST ['foo'] [0] 'pour la 10ème fois. –

2

suggestion One. Ajouter le mot de passe dans la course de hachage de salage:

$hash = hash('sha256', $pass); 
$salt = createSalt(); 
$hash = hash('sha256', $salt . $hash . $pass); 

La raison est d'éviter les collisions (mais avec SHA-256 qui est assez peu probable). Disons qu'il est une chaîne foo qui entre en collision avec votre mot de passe bar lorsqu'il est exécuté par sha256 ... $hash du premier tour serait identique, de sorte que le second tour de hachage produira également des résultats identiques:

$hash = hash('sha256', 'foo'); // "test" for example 
$hash = hash('sha256', 'bar'); // "test" since it's a collision 

$newHash = hash('sha256', $salt . $hash); //The same for both foo and bar! 

Alors que si vous réintroduire le mot de passe dans le deuxième tour, il ne sera pas directement entrer en collision puisque la chaîne est différente pour chaque tour de hachage ...

Modifier: En ce qui concerne le salage, je recommanderais quelque chose comme ça (multiplateforme):

function createSalt() { 
    $length = mt_rand(64, 128); 
    $salt = ''; 
    for ($i = 0; $i < $length; $i++) { 
     $salt .= chr(mt_rand(33, 255)); 
    } 
    return $salt; 
} 

Il utilise des caractères en dehors de la plage normale (beaucoup plus élevée), mais exclut les caractères communs de contrôle et d'espace qui peuvent être supprimés par la base de données (ou supprimés). Notez qu'il renvoie une chaîne ISO-8859-1 (Latin-1) valide. Ce n'est pas une chaîne UTF-8 valide. Donc, assurez-vous que le jeu de caractères de la colonne est bon, ou dans le pire des cas 255 à 127 dans le code ci-dessus (mais cela réduit considérablement la force du sel) ...

+0

Merci beaucoup pour la fonction sel. J'apprécie vraiment toute l'aide. La suggestion est géniale aussi! Merci pour toute l'aide. – mcbeav

+2

+1 pour vous aussi. Bien que les risques de collision soient toujours présents, les coups de foudre frappant votre billet de loterie que vous avez trouvé en faisant un détour sur une route jamais parcourue auparavant sont plus élevés. –

+1

@goreSplatter: Absolument, en supposant que nous parlions des détails d'implémentation de 'sha-256'. Si c'était "md5", alors c'est comme si vous étiez frappé par la foudre une fois dans votre vie ... – ircmaxell

Questions connexes