YBET

Rue Albert 1er, 7

6810 Pin - Chiny

Route Arlon - Florenville

(/fax: 061/32.00.15

Les formations sur Internet

Magasin YBET informatique Forum webmaster Créer son propre site

26.1. Cryptage et utilisation des cookies: exercice.

1. Méthodes d'encryptage - 2. Récupérer les cookies - 3. Exemple d'utilisation: login - mot de passe - 4. Mise à jour du cookie - 5. Vérification de l'utilisateur - 6. Gestion des utilisateurs dans les pages - 7. Pour conclure

Dans notre formation, nous avons utilisé les cookies avec le nom d'utilisateur et surtout le mot de passe en clair dans le contenu. Après les quelques explications sur le cryptage de textes en PHP, nous allons de nouveau utiliser les cookies mais cette fois en cryptant le mot de passe dans le cookie. En même temps, nous allons créer quelques fonctions spécifiques et coder également le mot de passe dans la table utilisateur. C'est une partie des directives de sécurité d'accès aux sites, même si elle n'est pas encore hautement sécurisée.

Comment allons procéder?

Vérification d'une demande de connexion
 { si Oui
 récupération nom utilisateur + mot passe
 cryptage du mot de passe
 vérification des données avec la table
 création d'un cookie
 }
 { si pas de demande de connexion
 vérification si le cookie existe déjà
  { si Oui
  récupération du cookie et contrôle avec la base de donnée
  récréation du cookie crypté si les données sont correctes
  }
}
Contenu de la page, formulaire de connexion inclus.

Cette méthode peut être implantée sur toutes les pages mais nous allons développer différemment. Une seule page va permettre de se connecter en reprenant le schéma ci-dessus. Les autres vont simplement vérifier si le cookie existe, le vérifier. Si les codes sont corrects, on le recrée et on permet l'accès à la page. Dans tous les autres cas, on interdit l'accès à ce visiteur non enregistré. Ce type de programmation n'est pas à utiliser pour un forum ou un système de vente mais bien pour des accès privés à des mails, dossiers privés, ...

1. Codage et décodage du mot de passe.

Lors de la création du compte utilisateur, nous allons d'abord créer un mot de passe aléatoire qui sera imposé à chaque nouvel utilisateur. Une fois créé, nous allons utiliser deux fonctions pour le coder et le décoder. Ces deux fonctions vont être insérés dans un fichier à part (includes/fonction.inc) appelé par chaque page du site. Pour crypter un texte, la fonction utilise une méthode ET une clé. De nouveau, nous allons utilisé un fichier séparé dans le dossier includes, sécurisé par HTaccess: configuration.inc. La clé ne pourra pas être modifiée plus tard sans recrypter tous les mots de passe dans la base de donnée.

configuration.inc

<?php
$cle_cryptage="Bonjour, voici ma clé";
?>

fonction.inc (inclus les fonctions).  L'algorithme utilisé est MCRYPT_RIJNDAEL, le mode est ECB

function cryptage($sans)
{
include ('configuration.inc');
// echo "chiffrage <br>";
$iv= mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256,MCRYPT_MODE_ECB), MCRYPT_RAND);
$chiffre= mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $cle_cryptage,$sans, MCRYPT_MODE_ECB,$iv);
$chiffre= mcrypt_encrypt($algo, $cle_cryptage, $sans, $mode,$iv);
return $chiffre;
}

/// **************** DECRYPTAGE mot de passe
function decryptage($chiffre)
{
include ('configuration.inc');
$iv= mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256,MCRYPT_MODE_ECB), MCRYPT_RAND);
$dechiffre= mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $cle_cryptage,$chiffre, MCRYPT_MODE_ECB,$iv);
return $dechiffre;
}

Chaque fonction récupère la clé dans le fichier de configuration. Chaque fois qu'une page récupère un mot de passe crypté via un cookie, il va appeler la fonction decryptage. A l'inverse, la fonction qui va gérer les cookies va récupérer le mot de passe crypté dans la table, le décoder via cryptage(), le comparer avec celui récupéré. Si les deux sont égaux, cette fonction va recréer le fichier de suivi en cryptant le mot de passe.

2. Récupération et décodage du cookie.

Reprenons quelques bases sur l'utilisation des cookies. La fonction setcookie doit être envoyée avant tout affichage ou en-tête html. Nous avons déjà analysé la méthode de programmation: dès le début nous vérifions la présence du cookie et l'analysons s'il est présent. Dans le cas d'une connexion via un formulaire, nous appelons simplement une fonction qui vérifie les codes utilisateurs et crée le cookie.

2.1. Fonction de création du cookie.

Reprenons l'exemple de la page précédente avec un simple formulaire de connexion utilisateur (nom - password). Nous le récupérons en début de page (juste après la gestion des cookies). La table utilisateur intègre seulement 2 champs: code et code_passe pour faire simple.

Envoi de $_POST['Connection'], récupération du nom et password entrés dans le formulaire via une fonction ADDSLASHES(). Le mot de passe est ensuite crypté via la fonction cryptage() ci-dessus. Par une requête MySQL, on vérifie si le mot de passe crypté entré par l'utilisateur est équivalent à celui crypté de la table utilisateur en utilisant le nombre de lignes renvoyées. Si la ligne est différente de 1, l'utilisateur est inconnu ou le mot de passe est faux: on assigne un message d'erreur à $erreur_contact. Sinon, on envoie deux cookies avec comme nom utilisateur, un pour le login reprenant le nom d'utilisateur et un pour le mot de passe (pass), reprenant le mot de passe crypté.

<?PHP
include ('includes /fonction.inc');
$erreur_contact="";
 if (isset ($_POST["Connexion"]))
{
 $nom=ADDSLASHES($_POST['nom']);
 $password=ADDSLASHES($_POST['mot_passe']);
 $code_passe_crypte=ADDSLASHES(cryptage($password));
  // Vérification des données entrées par l'utilisateur
 include ('includes/start.php');
 $requete="select code_passe FROM utilisateur WHERE code='$nom' AND code_passe='$code_passe_crypte'";
 $resultat=mysql_query($requete);
 $ligne=mysql_num_rows($resultat);
 if ($ligne<>1)
 {
  $erreur_contact="Nom de compte ou mot de passe inconnu, merci de recommencer ou de vous inscrire";
 }else
  {
  Setcookie('utilisateur[login]',$nom,time()+3600);
Setcookie('utilisateur[pass]',$code_passe_crypte,time()+3600);
 }
}

Cette partie n'est utilisée que lors de la première connexion, nous simplement vérifier si le cookie est présent, vérifier s'il correspond à un utilisateur et le régénérer si c'est le cas. Prévoyez quand même quelques possibles problèmes avec Explorer à partir de la version 8.

2.2. Récupération du cookie et vérification à partir de la table utilisateur

Une fois le cookie créé lors de la connexion, chaque page va vérifier si le cookie existe, récupérer les données et les comparer avec la table utilisateur. Nous allons utiliser une fonction pour cela. En fin de fonction, nous renvoyons simplement deux valeurs (via une matrice): le nom d'utilisateur et le mot de passe.

function gestion_cookies()
{
$retour=array();
date_default_timezone_set('Europe/Brussels');

// header ("Content-Type:text/html; charset=utf-8>"); // peut être nécessaire pour pouvoir gérer certains les hébergements
if(isset($_COOKIE['gestion']['login]'))
{
$login=$_COOKIE['utilisateur'] ['login'];
$password=cryptage($_COOKIE['utilisateur'] ['pass']);

include ('includes/start.php');
$requete="select * FROM liste_entreprise WHERE code='$login' AND code_passe='$password'";
$resultat=mysql_query($requete);
$ligne=mysql_num_rows($resultat);
$password=decryptage(STRIPSLASHES($password));
while ($tableau=mysql_fetch_array($resultat))
{
$numero1= $tableau['numero'];
$version=$tableau['version'];
}
$erreur1=mysql_error();
print($erreur1);
if ($ligne==0)
{
// cookie OK mais login ou mot de passe inconnu
$retour[0]='Login ou password inconnu';
$retour[1]='';
}
}else
{
// code correct, on renvoie le type de compte et redéfinit le cookies
$password_crypte=addslashes(cryptage($password));
Setcookie('utilisateur[login]',$nom,time()+3600);
Setcookie('utilisateur[pass]',$code_passe_crypte,time()+3600);

$retour[0]=$login;
$retour[1]=$password;
}
}
if (!ISSET($_COOKIE['utilisateur']['login']))
{
// cookies non acceptés ou cookies gestion non crée.
$retour[0]='Merci de vous connecter';
$retour[1]='';
}
return $retour;
}

3. Le développement final.

Au final, on retrouve deux structures de pages différentes: une utilisée pour la page index qui permet la connexion et toutes les autres pages qui vont simplement permettre l'accès à au contenu de chaque page uniquement si le cookie est bien valide en recréant le fichier de suivi. Pour vos propres développements, vous pouvez utiliser sur toutes les pages la même structure que celle d'entrée ici. Nous intégrerons les fonctions créées plus haut..

3.1. La page d'entrée.

C'est la seule qui permet la connexion utilisateur et la seule visible sans être connecté, sa structure est donc différente de toutes les autres pages. Une connexion correcte renvoie (fonction die) vers une page entrée.php qui elle va tester la présence des cookies textes et vérifier la correspondance du contenu. Pour faciliter la lecture, nous remplacerons le contenu par un simple commentaire. A vous d'utiliser votre propre contenu et d'adapter

// on reprend les deux fichiers de fonction
include ('includes/fonction.inc');
include ('includes/configuration.inc');
$erreur_contact="";
// tests de la demande de connexion
if (isset ($_POST["Connexion"]))
{
$nom=ADDSLASHES($_POST['nom']);
$password=$_POST['mot_passe'];
$code_passe_crypte=ADDSLASHES(cryptage($password));
include ('includes/start.php');
$requete="select code,code_passe FROM utilisateur WHERE code='$nom' AND code_passe='$code_passe_crypte'";
$resultat=mysql_query($requete);
$ligne=mysql_num_rows($resultat);

 if ($ligne<>1)
 {
  $erreur_contact="Nom de compte ou mot de passe inconnu, merci de recommencer ou de vous inscrire";
 }else
 {
  SETCOOKIE('utilisateur[login]',$nom,time()+3600);
  SETCOOKIE('utilisateur[password]',$code_passe_crypte,time()+3600);
 die('<meta http-equiv="refresh" content="1; URL=entree.php">');
 }
}
?>
<!-- <header>, contenu en HTML / PHP -->

<?php
echo $erreur_contact;
?>
<form method="POST">
<p>Adresse mail (nom utilisateur): <input type="text" name="nom" size="30"><br>
Mot de passe: <input type="password" name="mot_passe" size="20"><br>
<input type="submit" value="Se connecter" name="Connexion">
</form>
<!-- suite du code -->

3.2. Les autres pages.

La page de démarrage ne sert finalement que de page de transit qui permet d'accéder à une autre page sécurisée. Une fois connecté, l'utilisateur va avoir accès à l'ensemble des autres pages. Sur chacune, on va simplement vérifier la présence du fichier de suivi, comparer son contenu avec la base de donnée utilisateur. Si l'utilisateur est accepté, il accède à la page, sinon, il est renvoyé vers la page de démarrage immédiatement. En gros, en tout début de code, on récupère le fichier et le teste. S'il n'est pas présent ou correct, une redirection vers la page de connexion.

<?php
include ('includes/fonction.inc');
$retour =array();
$retour[1]='';
$retour=gestion_cookies();
IF ($retour['1']<>'')
{
$login=$retour['0'];
$password=$retour['1'];
// on reprend le menu avec les paramètres de la société.
?>
<!-- contenu de la page -->
<?php
} else
{
// gestion des cookies: connexion refusée.
Echo "Désolé mais cette fonction est réservée aux membres connectés";
die('<meta http-equiv="refresh" content="3; URL=index.php">');
}
?>

Si vous analysez le code, vous remarquez que la condition connecté (ou non) utilise la variable $retour[1]. Un bricolage sur cette variable pourrait permettre à un visiteur malintentionné d'utiliser cette faille potentielle de sécurité malgré qu'elle est revérifiée à chaque chargement de page. Pour cela, il lui faudrait connaître cette variable de condition (donc finalement le code) mais c'est possible. En pratique, on va utiliser d'autres variables supplémentaires ou même revérifier chaque fois via le nombre de lignes récupérée de la table utilisateur en comparant les valeurs de retour.

4. Pour terminer.

Voici la méthode de gestion des cookies sécurisés en pratique. Pourtant, en utilisant cette méthode, un "hackeur" peut modifier la variable de retour pour la condition (à condition de connaître le code PHP des pages) mais aussi, s'il connaît un mot de passe en clair, utiliser le mot de passe crypté dans le cookie pour récupérer la clé de cryptage ET le type de cryptage.

> 27. Méthodes Left et Join, commandes relationnelles
<26 . Le cryptage

Mise en ligne: 02/05/2012