Securiser une connexion

Mammouth du PHP | 620 Messages

18 janv. 2017, 14:34

Bonjour,
je viens d'adapté ce petit code qui me permettra de me connecter à l'admin de mon site mais je voudrais avoir votre avis.
Peut-on le sécuriser plus ?
Merci de vos retour instructifs.

Code : Tout sélectionner

<?php $dbconn = pg_connect("host=xxxx port=xxxx dbname=xxxx user=xxxx password=xxxx") or die('Connexion impossible : ' . pg_last_error()); $select = "SELECT * FROM users WHERE nom = '" . $_POST["utilisateur"] . "'"; $clients = pg_query($dbconn,$select) or die ('Error in query procedural --> '.pg_last_error()); while($test = pg_fetch_array($clients)) { // Definition des constantes et variables $mdp = $test["mot_de_passe"]; $login = $test["nom"]; $errorMessage = ''; } // Test de l'envoi du formulaire if(!empty($_POST)) { // Les identifiants sont transmis ? if(!empty($_POST['utilisateur']) && !empty($_POST['mdpass'])) { // Sont-ils les mêmes que les constantes ? if($_POST['utilisateur'] !== $login) { $errorMessage = 'Mauvais login !'; } elseif(md5($_POST["mdpass"]) !== $mdp) { $errorMessage = 'Mauvais password !'; } else { // On ouvre la session session_start(); // On enregistre le login en session $_SESSION['utilisateur'] = $login; // On redirige vers le fichier admin.php header('Location: /admin.php'); exit(); } } else { $errorMessage = 'Veuillez inscrire vos identifiants svp !'; } } ?>

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

18 janv. 2017, 15:55

salut,

md5 n'est plus considéré comme sécurisé il y a des tables énorme de mot dictionnaires permettant de retrouver le texte clair de façon rapide et simple (il y a même de site où tu fournit les hash et ils te retourne le texte en clair ;)

utilise plutôt password_hash

n'indique pas ce qui déconne demande simplement de vérifier les info (sinon tu indiques que l'utilisateur est bon reste a faire un brute force sur le mot de passe.

plus grave ton code est sensible à l'injection SQL
$select = "SELECT * FROM users WHERE nom = '" . $_POST["utilisateur"] . "'";

as ton avis que ce passe t'il si en utilisateur on met
admin'; update users set pwd='toto
certes il faut connaitre le nom de la table mais imagine un peu ce que l'on peu ensuite faire. (un un drop database, ou des tables par exemple ....).

je te conseil de protéger ta chaine correctement => pg_escape_string

au pire utilise une requête préparée pg_prepare

tu peux aussi utiliser PDO en lieu et place de l'extension PG ;)

tu n'as pas besoin de boucler sur le jeux de résultat tu ne doit avoir qu'un seul utilisateur qui correspond au pseudo (un clef unique me semble obligatoire sur ce type de colonne) sinon c'est un beau bordel c'est la dernière ligne qui gagne comment peux tu être certain de te connecter avec le bon utilisateur ?


voilà comment on peu faire au minimum
<?php

// Test de l'envoi du formulaire (on vérifie les deux champ ici)
if(!empty($_POST['utilisateur']) && !empty($_POST['mdpass']))
{
    $dbconn = pg_connect('host=xxxx  port=xxxx dbname=xxxx user=xxxx password=xxxx')
    // le die c'est à proscrire il faut afficher un message d'erreur non technique et sans péter la charte graphique pour éviter le désagrément d'une page blanche avec un message d'erreur fournit par pg que persone comprend
    or die('Connexion impossible : ' . pg_last_error());
    $userName = pg_escape_string($_POST['utilisateur']);
    // que le mot de passe le reste on s'en fou et le nom on l'a déjà
    $select = 'SELECT mot_de_passe FROM users WHERE nom = ' . $userName;
    
    $clients = pg_query($dbconn,$select);
    
    if($client === false){
        // erreur voir pour afficher un truc propre et pas de die :-)
    }
    
    $userData = pg_fetch_assoc($clients);
    
    if(password_hash($_POST['mdpass'],PASSWORD_BCRYPT) !== $userData['mot_de_passe'])
    {
        $errorMessage = 'erreur d\'authentification. utilisateur ou mot de passe incorrecte';
    }
    else
    {
        // On ouvre la session
        session_start();
        // On enregistre le login en session, un ID serait interressant afin de retrouver simplement les choses qui appartient à l'utilisateur connecter (il ne faut pas faire de jointure avec un nom / pseudo
        $_SESSION['utilisateur'] = $userName;
        // On redirige vers le fichier admin.php
        header('Location: /admin.php');
        exit();
    }
    
    // les deux lines suivantes sont importantes
    
    // libère la mémoire occupée par le résultat de la requête
    pg_free_result($clients);
    // on ferme la connexion si plus besoin
    pg_close($dbconn);
}else
{
    $errorMessage = 'Au moins un des champs obligatoire est vide';
}

// inclusion du début de la page avec la charte graphique
if(!empty($errorMessage)){
    echo '<div class="error_message">',$errorMessage,'</div>';
}

// inclusion du pied de page
bien sur ajoute la dessus une connexion https pour faire bien ;)


@+
Il en faut peu pour être heureux ......

Mammouth du PHP | 620 Messages

19 janv. 2017, 18:50

Bonjour et merci.
j’essaie de mettre en place donc ce nouveau code plus sécurisé mais je rencontre un soucis car du coup avec le passwordhash je n'arrive plus a me connecter.
j'ai recréé un nouvelle utilisateur manuellement dans la base en mettant en mot de passe, un mot de passe que j'ai créé sur avec un generateur ce site.
du coup j'ai toujours le message "erreur d'authentification. utilisateur ou mot de passe incorrecte"

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

19 janv. 2017, 19:03

Bonjour,

Utilises-tu bien password_verify() pour vérifier la concordance entre le mot de passe saisi et le hash stocké ?
http://php.net/manual/fr/function.password-verify.php
Quand tout le reste a échoué, lisez le mode d'emploi...

Mammouth du PHP | 620 Messages

19 janv. 2017, 22:13

et bien en fait j'ai remplacé dans le code moogli la ligne :

Code : Tout sélectionner

if(password_hash($_POST['mdpass'],PASSWORD_BCRYPT) !== $userData['mot_de_passe'])
par

Code : Tout sélectionner

if(password_verify($_POST['mdpass'],PASSWORD_BCRYPT) !== $userData['mot_de_passe'])
mais j'ai toujours l'erreur de login/motdepasse.

Pour ajouté mon mdp dans ma base j'ai fais comme cela pour etre sur que le hash soit ok.

Code : Tout sélectionner

$motdepasse = password_hash("monmd@pass", PASSWORD_BCRYPT); ... puis requet intégration.

Mammouth du PHP | 1967 Messages

20 janv. 2017, 09:12

Si tu clique sur le lien fourni par @rthur, tu verra très vite comment utilisé password_verify

boolean password_verify ( string $password , string $hash )

Cela veut dire que la fonction retourne un boléun (vrai ou faux) et prend en paramètre le mot de passe en clair et le hash de ta BDD.
if(password_verify($_POST['mdpass'],$userData['mot_de_passe']))
Spols
pour les fan de rubik's cube ou pour les curieux ==> le portail francophone du rubik's cube