Sécuriser votre site Internet en PHPIntroductionJ'ai rédigé cet article lors de mon rapport de stage, donc je mets en ligne la partie sur la sécurisation de votre site Internet en PHP. Je ne prétends pas tout savoir mais si vous développez votre propre site Internet, cet article vous évitera les erreurs basiques et donc bien des désagrements ! Bien que je préfère utiliser les systèmes d'exploitation sous Windows 2003 Server ou UNIX au lieu de coder, j'ai été emmené à développer des applications et j'ai toujours accès mon code sur la sécurité car c'est le plus important ;) J’utilise NotePad++ pour coder. Je vais présenter l’organisation des pages de configuration que j’utilise en PHP. Le code fonctionne en PHP4, il n’y a donc pas de classe et méthodes comme le langage Orienté Objet. Le code est abrégé pour une meilleure lisibilité. Je commente les lignes après le code complet. Connexion à la base de données<?php $serveur="localhost"; $utilisateur="root"; $motDePasse=""; $base="egc"; $table1='utilisateur'; $table2='stage'; $table3='emploi'; //connexion a la base @mysql_connect($serveur, $utilisateur , $motDePasse) or die("Impossible de se connecter au serveur de bases de données."); @mysql_select_db($base) or die("Base de données non trouvée."); ?> Pour se connecter à une base de données de type MySQL par exemple, il est judicieux de créer un fichier « connection.inc.php » et d’y stocker l’adresse du serveur, l’utilisateur du compte MySQL, le mot de passe ainsi que le nom de la base de données. Pourquoi ? Dans un souci de maintenance du code, il est judicieux de tout mettre dans le même fichier, ainsi, lorsqu’une page PHP a besoin d’une connexion à MySQL, il n’est pas nécessaire de réécrire les paramètres de connexion, une simple ligne appelant cette page est à réaliser : « @require(‘connection.inc.php’) ; ». Dans ce fichier, je stocke également les noms des tables de ma base. Dans quel but ? Cela me permet de renommer une table sans modifier tout mon code, ainsi, dans mes pages, quand j’écris une requête j’utilise « $table1 » au lieu d’ « utilisateur » tout simplement. Je définis ensuite la chaîne de connexion pour me connecter à la base de données, ici il s’agit de la base « egc » qui contient les tables « utilisateurs », « stage » et « emploi ». Les « @ » avant les fonctions de connexion oblige PHP à ne pas afficher les erreurs relatives à la connexion. De ce fait, seul les chaînes de caractères dans le « die » sont affichées. Cela évite de donner de potentielles indices aux personnes mal intentionnées. Sécurisation de cette connexionIl est possible d’augmenter la sécurité du fichier de connexion décrit plus haut en interdisant l’accès à tous sauf au serveur Web. Pour se faire, il faut placer le fichier « connection.inc.php » dans un dossier à la racine de votre site, la encore, n’hésitez pas à le placer dans un dossier comportant un nom difficile tel que « tuk25L ». Dans ce dossier, il faut utiliser les fichiers .HTACCESS qui permettent de définir des règles. Dans notre application, nous souhaitons empêcher la lecture du fichier « connection.inc.php ». Dans le dossier où se situera « connection.inc.php », créez un nouveau fichier que vous nommerez « .htaccess », n’oubliez pas le « . » avant le nom du fichier. Windows peut vous empêcher de le créer (vous n’aurez pas ce souci sous Linux) donc créer le fichier sans le « . » puis transférer le fichier « htaccess » par FTP chez votre hébergeur et vous pourrez rajouter le « . » en le renommant. Dans le fichier « .htaccess » placez ce code : deny from all allow localhost Ainsi, seul le serveur Internet pourra accéder au dossier contenant le fichier de connexion et pas les visiteurs. L’affichage du dossier dans un navigateur Internet se soldera par une erreur 500 ; le fichier de connexion est donc protégé. Sachant que les scripts locaux ont accès au dossier, il y’a une limite : si un script d’envoi de fichier est mal codé sur le site, un internaute pourrait envoyer un fichier PHP sur le serveur et en l’exécutant, il pourrait afficher le contenu du fichier de connexion, car le script serait exécuté localement donc il pourrait accéder au dossier protégé. si une personne possède un accès sur le serveur il pourra accéder au dossier mais ce cas est rarissime car la sécurité du serveur est sérieusement compromise. Gestion des rangs au sein de l’application InternetPour la gestion des rangs, par exemple entre administrateurs et utilisateurs logués, il faut utiliser les sessions en PHP (Documentation sur les sessions). Dans cet exemple, je vais protéger la page « membre.php » par un accès réservé aux membres. Cette page se situe à la racine du serveur Internet. La gestion des utilisateurs est gérée par une table MySQL contenant les identifiants de chaque personne : ![]() Identification et création des sessions Le formulaire d’identification est en HTML : <form method="post" action="traitement_identification.php" > <table align="center" class="tab_stage"> <tr> <td width="110">< b>Login :< /b>< /td> <td><input maxlength="20" size="20" name="pseudo" /></td> </tr><tr> <td width="110">< b>Mot de passe :</b></td> <td><input maxlength="20" size="20" name="mot_de_passe" type="password" /></td> </tr><tr> <td align="center"><input type="Reset" value="Effacer" /></td> <td align="center"><input type="submit" value="Envoyer" />< /td> </tr> </table> </form> Le script qui va traiter l’identification : <?php session_start(); @require('./dossierprotege/connection.inc.php'); function securite($texte){ if (get_magic_quotes_gpc()) { $texte = trim(mysql_real_escape_string(stripslashes($texte))); } else { $texte = trim(mysql_real_escape_string($texte)); } return $texte; } $pseudo = securite($_POST["pseudo"]); $mot_de_passe = securite($_POST["mot_de_passe"]); if(strlen($pseudo) > 0 || strlen($mot_de_passe) > 0) { //verif pseudo et mot de passe et récupération du rang de l'utilisateur $resultat = mysql_query("SELECT id_utilisateur,login_utilisateur,mot_passe_utilisateur,rang_utilisateur FROM $table1 WHERE login_utilisateur='".$pseudo."' AND mot_passe_utilisateur=PASSWORD('$mot_de_passe')"); $ligne = @mysql_fetch_array($resultat); // création de la session if ($ligne) { $_SESSION['pseudo'] = $ligne['login_utilisateur']; $_SESSION['rang'] = $ligne['rang_utilisateur']; $_SESSION['id'] = $ligne['id_utilisateur']; header ("Location: membre.php"); // renvoit l'utilisateur sur la page espace_membre.php exit(); } else { header ("Location: identification.php"); // renvoit l'utilisateur sur la page précédente exit(); } } else { header ("Location: identification.php"); // renvoit l'utilisateur sur la page précédente exit(); } ?> On démarre les sessions avec « session_start() ; ». On appelle ensuite le fichier de connexion créé précédemment pour que le script puisse se connecter à MySQL. La fonction « securite » filtre les entrées fournies par l’utilisateur en utilisant les fonctions de MySQL. Si l’utilisateur renseigne bien son login et mot de passe, alors les sessions sont crées pour le login, le rang ainsi que son ID issu de la table UTILISATEUR. Suivant les données issues de la table UTILISATEUR, l’utilisateur logué aura une valeur pour la colonne « RANG ». Nous allons pouvoir travailler avec cette valeur : « $_SESSION['rang'] » pour faire des traitements. On utilise la fonction « PASSWORD » qui va convertir le mot de passe rentré par l’utilisateur en le hachant au format MD5 puis il est comparé au mot de passe (au format MD5) stocké dans la table UTILISATEUR. S’ils sont identiques, alors l’utilisateur a rentré son mot de passe, il est redirigé sur la page « espace_membre.php » sinon il est renvoyé sur la page précédente. Protection d’une page aux personnes loguées Il faut protéger la page « espace_membre.php » car une personne pourrait accéder à cette page en tapant l’adresse directement dans son navigateur. Voici le code à placer au début de la page espace : session_start(); @require('./dossierprotege/paslogue.inc.php'); Le script « paslogue.inc.php » (placé dans le même dossier que le fichier « connection.inc.php ») contient : <?php @require('./dossierprotege/connection.inc.php'); // *************** Obligation login ********************** if (!isset($_SESSION['pseudo']) && !isset($_SESSION['rang']) && !isset($_SESSION['id'])) { header('Location: identification.php'); exit(); } // ********** FIN Obligation login ************************** ?> Ainsi, si un utilisateur tente d’accéder à la page « membre.php », le script vérifie qu’il possède une session, s’il n’en possède pas, il est renvoyé sur le page « identification.php » sinon, la page « membre.php » continue son exécution. Administration Une partie du site est réservée aux administrateurs, ils sont identifiés par un rang « admin ». Une fois logué sur le site, la variable « $_SESSION['rang'] » contient « admin » alors qu’un utilisateur classique contiendra « normal ». Ainsi, pour protéger une la page « administration.php » (ou n’importe quelle autre page), il faut utiliser un script semblable à « paslogue.inc.php ». Le script sera nommé « reserveadmin.inc.php ». <?php @require('./dossierprotege/connection.inc.php'); // ******** Obligation login ****************************** if (!isset($_SESSION['pseudo']) && !isset($_SESSION['rang']) && !isset($_SESSION['id'])) { header('Location: ../identification.php'); exit(); } elseif ($_SESSION['rang'] == 'normal') { header('Location: ../identification.php'); exit(); } elseif ($_SESSION['rang'] <> 'admin') { header('Location: ../identification.php'); exit(); } // ********* FIN Obligation login *************************** ?> Pour utiliser ce script, placez ce code en tête de votre fichier à protéger : session_start(); @require('./dossierprotege/reserveadmin.inc.php'); Si une personne dont le rang est différent de « admin » tente d’accéder à la page « administration.php » il sera renvoyé sur la page « identification.php ». Par contre, si une personne dont le rang est « admin », il aura accès à la page « administration.php » car le script « reserveadmin.inc.php » ne stoppera pas l’exécution du script. Déconnexion Pour qu’un utilisateur se déconnecte, il faut utiliser ce script : session_start(); // Détruit toutes les variables de session session_unset(); // Finalement, détruit la session session_destroy(); // retour au début header ("Location: index.php"); ?> L’internaute aura sa session détruite et il sera redirigé sur la page « index.php ». Architecture du site InternetLes pages du site se découpent en 3 parties : * entête * milieu * pied Il s’agit d’utiliser des « pseudo-frames ». Chaque partie « milieu » va inclure l’« entête » et le « pied ». La maintenance est plus simple, chaque modification de la partie « entête » est répercutée sur toutes les pages ! La partie « entête » contient le menu, la bannière, le design supérieure du site. La partie « entête » (haut.php) contient : <?php // définition du nom de domaine $domain_name = 'http://localhost/egc/'; ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <link href="style.css" rel="stylesheet" type="text/css"> <title><?php echo $titre_page; ?></title> </head> <body> La variable « $domain_name » contient l’adresse Internet, cela permet de changer toutes les adresses du site d’un seul coup et ainsi passer d’une adresse locale à une adresse en .com rapidement. Il faut juste mettre « » avant chaque lien. Le « DOCTYPE » est un élément obligatoire établi par le W3C pour la bonne gestion des CSS entre les différents navigateurs. Pour plus d’informations, visitez cette page : http://www.w3.org/QA/Tips/Doctype Entre les balises « title » l’utilisation du PHP permet de générer dynamiquement le titre suivant la partie centrale qui inclue l’entête. Ainsi, avant chaque appel de l’entête, il faudra assigner une valeur à « $titre_page ». Il faut placer ce code au début de la page du milieu : < ?php $titre_page = ‘Accueil – Bienvenue sur le site’ ; @require(‘haut.php’) ; ?> Ainsi, toute la partie « entête » sera recopiée dans la partie « milieu » de la page. Elle aura pour titre : Accueil – Bienvenue sur le site. La partie « pied » (bas.php) contient : </body> </html> Il faut placer ce code à la fin de la page du milieu : <?php @require(‘bas.php’) ; ?> Création d’une page de test : index.php <?php $titre_page = ‘Accueil – Bienvenue sur le site’ ; @require(‘haut.php’) ; ?> Bla bla bla bla bla bla bla bla bla bla. Bla bla bla bla bla bla bla bla bla bla. <?php @require(‘bas.php’) ; ?> Si vous visualisez le code source généré par votre navigateur sur la page « index.php » qui inclue la page « haut.php » et « bas.php », vous remarquerez qu’index.php est valide et comporte l’ensemble des pages haut.php et bas.php. La gestion du site est simplifiée : la modification d’un menu n’exige plus le traitement de toutes les pages du site mais seulement de la partie « haut.php », il en est de même pour la partie « bas.php » qui va contenir le copyright par exemple ; une modification de l’année du copyright sera visible sur tout le site. ConclusionJ'espère que cet article vous permettra de renforcer la sécurité dans vos sites Internet. |






