IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Explication sur un bout de code


Sujet :

PHP & Base de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 236
    Par défaut Explication sur un bout de code
    Bonsoir,

    Dans ce code :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    <?php
    include "BDD/identifiant.php"; 
    require ("class/class.phpmailer.php");
     
    if(isset($_POST['submit']))
    {
    	include "connexionBD.php";
     
    	//Les différents input.
     	$pseudo = utf8_decode($_POST['pseudo']);
    	$mdp = sha1($_POST['mdp']);
    	$rmdp = sha1($_POST['rmdp']);
    	$email = utf8_decode($_POST['email']);
    	$nom = utf8_decode($_POST['nom']);
    	$prenom = utf8_decode($_POST['prenom']);
    	$annee = ($_POST['annee']);
    	$sexe = utf8_decode($_POST['sexe']);
    	$adresse = utf8_decode($_POST['adresse']);
    	$cp = utf8_decode($_POST['cp']);
    	$ville = utf8_decode($_POST['ville']);
    	$telephone = utf8_decode($_POST['telephone']);
    	$categorie = utf8_decode($_POST['categorie']);
    	$type_licence = utf8_decode($_POST['type_licence']);
    	$club = ( isset($_POST['club']) )? utf8_decode($_POST['club']) : '';					//on appelle une condition ternaire : var = ( condition )? [valeur si vrai] : [valeur si faux] 
    	$licence = ( isset($_POST['licence']) )? utf8_decode($_POST['licence']) : '';
    	$compte = utf8_decode($_POST['compte']);
     
    	// Vérification si deux pseudo sont identiques dans la bade de données.
    	$req = 'SELECT pseudo FROM `bdd`.`inscription` WHERE pseudo = ?';
     
        $prepa = mysqli_prepare($connexion, $req);				//Prépare la requète.
     
        mysqli_stmt_bind_param($prepa ,'s', $pseudo);			//Lie les variables à la requête précédement inscrite.
     
        $prepa->execute();										//Execute la requête.
     
        $resultat = mysqli_stmt_fetch($prepa);					//Retourne le résultat de la requête.
     
    	if ($resultat)											//Vérifie si le pseudo existe.
    	{
    	    echo '<p id="mauvais">Pseudo déjà existant, veuillez en entrer un autre.</p><br>';
    	}
     
    	// Vérification si deux emails sont identiques dans la bade de données.
    	$req = 'SELECT email FROM `bdd`.`inscription` WHERE email = ?';
     
        $prepa = mysqli_prepare($connexion, $req);				//Prépare la requète.
     
        mysqli_stmt_bind_param($prepa ,'s', $email);			//Lie les variables à la requête précédement inscrite.
     
        $prepa->execute();										//Execute la requête.
     
        $resultat = mysqli_stmt_fetch($prepa);					//Retourne le résultat de la requête.
     
    	if ($resultat)										//Vérifie si le mail existe.
    	{
    	    echo '<p id="mauvais">Email déjà éxistante, veuillez en entrer une autre.</p><br>';
    	}
     
    	else if ($mdp == $rmdp)
    	{
    		//Si tout est correct, on rentre les valeurs dans la base.
    	 	$sql = "INSERT INTO `bdd`.`inscription` (`id`, `pseudo`, `mdp`, `email`, `nom`, `prenom`, `annee`, `sexe`, `adresse`, `cp`, `ville`, `telephone`, `categorie`, `type_licence`, `club`, `licence`, `compte`)
    	 			VALUES ('', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; //Chaque ? représente une variable dans l'ordre indiquer dans la requete sql. ? pour dire que tu vas checker puis va rentrer dans la bdd
     
    	 	$stmt = mysqli_prepare($connexion, $sql);
     
    		//Paramètres : chaines de caractères dans l'ordre - Permet de renseigner les paramètres repéré par les "?" dans l'ordre.
    		mysqli_stmt_bind_param($stmt, 'ssssssssssssssss', $pseudo , $mdp, $email, $nom, $prenom, $annee, $sexe, $adresse, $cp, $ville, $telephone, $categorie, $type_licence, $club, $licence, $compte);
     
    		//Exécution
    		mysqli_stmt_execute($stmt);	//Execute la requête.
    		echo "<p>Inscription réussi.</p><br>";
     
    	}else echo '<p id="mauvais">Les mots de passes ne sont pas identiques.</p><br>';
    }
    ?>

    Malgré mes recherches je me pose toujours certaines questions.
    J'aimerais savoir comment marche la partie comprise entre les lignes 60 et 75.

    Je sais que j'insère dans la base de donnée les informations de mon formulaire mais ce que je ne comprends pas :

    - Pourquoi les "?" à la place de ":pseudo" ou "$pseudo" ?
    - On m'a dit que j'ai réalisé une requête sécurisé, comment puis-je le constater ?
    - Quelle ligne dois-je enlever pour réaliser une injection Mysql ? Ou pour que ma requête ne soit plus sécurisé ?
    - Je sais qu'il faut mettre autant de "s" qu'il y a de variable (i pour entier, d pour decimal et s pour chaine de caractères) mais à part ça, quel rôle ses "s" joues t-il ?

    J'ai aussi une erreur dans la vérification du pseudo, si il existe dans la bdd ou non :

    L'erreur, c'est soit je vérifie si le pseudo existe ou soit je vérifie si l'adresse mail existe, si j'insère les deux tâches en même temps j'ai des erreurs :

    Pour le pseudo déjà existant ça m'affiche ces erreurs mais l'inscription ne s’exécute pas :

    http://www.noelshack.com/2015-02-1420470843-capture.png

    Pour le mail déjà existant tout est correct :

    http://www.noelshack.com/2015-02-1420470714-capture.png

    Merci pour vos réponses.

  2. #2
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Par défaut
    C'est une requête préparée. Les "?" sont des paramètres non nommés qui sont donc identifiés uniquement par leur ordre, tandis que :pseudo est un paramètre nommé identifié par son nom.
    Pour que cette requête ne soient plus sécurisée, il faudrait enlever un paramètre et le remplacer par une variable venant du formulaire par exemple. L'utilisateur pourrait alors "injecter" du code SQL.
    http://fr.wikipedia.org/wiki/Injection_SQL
    http://php.net/manual/fr/security.da...-injection.php

    Pour ton erreur, cela vient probablement d'un problème dans la requête, il faut donc contrôler les erreurs mysql.
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 236
    Par défaut
    D'accord donc c'est principalement la ligne :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $sql = "INSERT INTO `bdd`.`inscription` (`id`, `pseudo`, `mdp`, `email`, `nom`, `prenom`, `annee`, `sexe`, `adresse`, `cp`, `ville`, `telephone`, `categorie`, `type_licence`, `club`, `licence`, `compte`)
    	 			VALUES ('', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

    Qui rend la requête sécurisé ?

    Dans un autre topic on m'a dit qu'il fallait que je "prépare" et "bind" chacune de mes requêtes pour que celle-ci soit sécurisé, si ce n'est pas le cas la requête comporte des failles ?

    Pour mes erreurs si je ne vérifie QUE le pseudo OU QUE l'adresse mail j'ai aucune erreur, dès que je veux faire les deux en même temps ça plante.

    Merci Tsilefy et Sabotage pour vos réponses précise.

    Si j'ai mis des "utf8_decode" partout c'est parce que je n'ai trouvé aucun moyen de rentrer les valeurs de mon formulaire dans la bdd tout en acceptant les accents, si je les enlèves j'ai des symboles qui apparaissent au lieux des accents.

    Pourquoi "sha1($_POST['mdp'])" est une mauvaise idée pour rentrer les mot de passes dans la bdd ? Ils sont bien cryptès pourtant mais ok j'utilise ton bout de code.

    Je pense avoir finalement compris l'utilisation des "?" alors, en gros elles permettent de remplacer automatiquement les variables c'est bien ça ?

    Non je ne vous demande pas de faire mon devoir, je pense comprendre le code de mon site web complétement mais cette partie était flou, jusqu'à que vous m'aidiez, merci à vous.

    Pour les erreurs, je penses tout simplement enlevé la vérification de l'email.

    Une dernière chose, comment je pourrais tester la sécurité ?
    C'est à dire enlever les lignes qui permette de sécuriser la requête pour pouvoir réaliser une injection Mysql..

    Comment je réalise cette injection ? J'ai vue sur le net que remplacer la fin de l'url par php?id=1' (avec l'apostrophe) permet d'en faire une mais quand je la réalise, rien ne se produit.

  4. #4
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Par défaut
    Une requête n'est pas sécurisée si tu places directement dedans des valeurs saisies par un utilisateur.
    La préparation comme tu le vois, sépare la requêtes des valeurs.

    Plutôt que d'utiliser utf8_decode, mets tous tes éléments en UTF8
    http://j-willette.developpez.com/tut...-site-en-utf8/

    La fiabilité de SHA1 a été remise en cause donc il vaut mieux utiliser autre chose puisqu'on en a la possiblité.

    Avec comme seule information "ça plante", je ne peux pas t'en dire sur ton problème.
    Il faut utiliser mysqli_error() pour avoir les erreurs mysql.
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  5. #5
    Membre Expert

    Profil pro
    Inscrit en
    Mai 2008
    Messages
    1 576
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 1 576
    Par défaut
    Sha1 n'a pas été conçu pour hasher les mots de passe. C'est un algorithme conçu spécialement pour être rapide (et donc rapidement déchiffrable) - regarde la doc, c'est écrit :-)
    Utiliser sha1 est donc vulnérable aux décryptages avec force brute et aux rainbow tables (des listes de mots de passe et les hash correspondants qu'on peut trouver un peu partout). Pour pallier à ça, on a pendant longtemps ajouté un "sel" (salt en anglais), c'est à dire une chaîne de caractère unique, comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    $mdp = "hunter2";
    $salt = "41ndhins3aznbge";
    sha1($mdp . $salt);
    Ça rendait le déchiffrage plus difficile et plus long, mais avec les progrès des processeurs graphiques, la facilité à utiliser le cloud pour former un calculateur surpuissant à base de petits serveurs virtuels (Amazon EC2, Ovh...) et la multiplication des rainbow tables à chaque hack d'un grand site web avec des millions d'utilisateurs), l'ajout de sel ne change plus rien.

    La seule solution est d'utiliser des algorithmes lents, conçus spécialement pour les mots de passe. Mais comme l'encryption est un domaine très, très pointu où il est facile de se tromper, mieux vaut utiliser ce que PHP propose directement depuis PHP 5.4. Avec password_hash (et son inverse password_verify), plus besoin de se casser la tête quand au choix de l'algo, à la génération du sel ou au stockage du sel dans une table.

  6. #6
    Membre très actif Avatar de zaza576
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2013
    Messages
    175
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Août 2013
    Messages : 175
    Par défaut
    Je rejoins mon camarade précédent sur l'usage d'algorithme de chiffrement / hachage lent.

    On peut éventuellement accompagner le mot de passe hashé et salé d'un temps de reconnexion exponentialisé par tentative de connexion échouée.

    Par exemple : un utilisateur saisi un login et mot de passe. S'il échoue, on va lui demander de ressaisir ce login et mot de passe, mais côté serveur, la tentative de reconnexion ne durera plus disons 1 seconde mais 2. Et pour chaque échec, tu multiplies ce temps par 2. Cela est une solution possible (pas forcément tout le temps efficace) contre le brute force.

    Autre idée : Au bout de trois tentatives de connexion échouées, on bannit l'adresse IP ainsi que le compte de l'utilisateur. Cela a pour effet d'être radical, plus de brute force possible. Cela demande par contre de gérer une blacklist d'adresses IP.

    Troisième solution : le formulaire de connexion pourrait être accompagné d'un troisième champ (les deux premiers étant login et mot de passe). Ce troisième champs peut être un captcha.

    Toutes ces solutions ont pour but d'augmenter légèrement la sécurité du formulaire mais elle n'assure en rien une protection optimale. De nos jours, les grands hackers utilisent des bots pour faire des DDOS, des attaques de type brute force centralisé, ... Contre cela, une seule solution : la hache !

  7. #7
    Membre Expert

    Profil pro
    Inscrit en
    Mai 2008
    Messages
    1 576
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 1 576
    Par défaut
    D'abord,

    - est-ce qu'il y a une raison particulière pour transformer les variables POST avec utf8_decode? Est-ce que tu sais ce que tu fais?

    - sha1($_POST['mdp']) est une très mauvaise idée pour stocker un mot de passe. La seule solution fiable est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    password_hash($_POST['mdp'])
    . Si la fonction n'est pas disponible sur ton PHP, utilise la même ici.

    - Le commentaire de ton code est clair sur la signification des "?"
    Chaque ? représente une variable dans l'ordre indiquer dans la requete sql.
    Si tu as 10 valeurs à insérer, tu doix utiliser 10 ? Tu ne peux pas utiliser :pseudo parce qu'à la différence de PDO, mysqli ne permet pas l'utilisation des paramètres nommés, qui permettent plus de flexibilité (d'où le conseil d'utiliser PDO plutôt que mysqli). Si tu utilises $pseudo, ça annule tout l'intérêt d'utiliser une requête préparée. La requête préparée permet de protéger la requête contre une injection en séparant la requête elle-même et les valeurs à manipuler. En utilisant $pseudo directement, tu combines de nouveau la valeur à la requête, ce qui rends ta requête très vulnérable.

    - Ta requête est sécurisée si tu utilises proprement les requêtes préparées, ce qui est le cas. Pour le vérifier, tu peux tenter de faire une injection MySQL sur ton site.

    - T'es sûr que tu n'es pas en train de nous demander de faire tes devoirs? http://php.net/manual/fr/mysqli-stmt.bind-param.php. i,d,s, b te permet d'être sûr que la valeur sera traitée comme un entier un décimal, une chaîne ou un blob. Cela évite des mauvaises surprises, comme par exemple lorsque la requête s'attends à un string et reçoit un entier à la place.

Discussions similaires

  1. Eclaircissements sur un bout de code
    Par namstou3 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 18/09/2007, 20h47
  2. Infos sur ce bout de code vb
    Par Freud44 dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 05/09/2007, 14h46
  3. explication d'un bout de code ASP
    Par mademoizel dans le forum ASP
    Réponses: 4
    Dernier message: 22/05/2007, 13h03
  4. explication sur un bout de code
    Par poporiding dans le forum C++
    Réponses: 2
    Dernier message: 27/06/2006, 18h04
  5. Besoin d'explications sur un bout de code
    Par zizitop dans le forum C
    Réponses: 7
    Dernier message: 26/04/2005, 14h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo