[Tuto] Sécuriser son site web



  • Salut a tous, vous avez surement envie de crée un site mais il y a un hic (c'est rare qu'il ni en ai pas), vous ne savez pas comment le sécurisé pour ne pas vous faire subtilisé des informations relative a votre site !
    Plusieurs choix s'offre a vous (vous n'aurez tout de même pas trop le choix :p) :
    **- Vous crée (ou modifier) votre site entièrement en xHTML mais encore un hic, votre site ne sera pas dynamique, ce qui veux dire les espace membres, formulaire de contact et tout sa ne sera pas possible ! (vous avez bien le JavaScript mais on n'ai jamais sur de rien avec le JS ;) )

    • Vous apprenez a sécurisé votre site sur le tas ce qui veux dire que vous devriez vous le faire piraté pour comprendre d'où vient la faille (ce qui n'est pas toujours évident a savoir si le pirate en question ne nous donne pas la faille)
    • Vous faite des études dans ce domaine
    • Vous suivez ce tutoriel**

    C'est bon ? Vous avez fait votre choix ? bien, je voit que vous êtes raisonnable :) poursuivons...

    La première chose a savoir c'est qu'il ne faut jamais faire confiance aux données crée par le visiteur, quand vous avez compris sa, vous avez déjà fait un grand pas.

    I. MYSQL
    Si vous avez un site, vous voudriez (je pense) faire un espace membre par exemple (tout dépend du type de site). Dans un espace membres nous avons grossomodo 1 formulaire de connexion et 1 formulaire d'inscription, les 2 formulaires vont touché la base de donnée mysql, l'un va y rentrée des informations et l'autre va y vérifier des informations.
    Imaginons que vous débutiez en PHP/MYSQL et que vous allez codé la page d'inscription (en 1 seul page, vous êtes un warrior, vous avez pas peur des défis). Voici ce que sa donne (oui j'ai bien dis débutant, sa va pas être un codage de lux :p) :

    <?php
    if($_GET['mpt'] == 1) // Vérifie que la variable mpt de type GET soit a 1
    {
    if(isset($_POST) AND !empty($_POST['login']) AND !empty($_POST['password']) AND !empty($_POST['email']) AND !empty($_POST['nom']) AND !empty($_POST['prenom'])) // Vérifie que tout les champs du formulaire sont remplies
    {
    
    mysql_query("INSERT INTO membres (login, password, email, nom, prenom) VALUES ('".$_POST['login']."', '".$_POST['password']."', '".$_POST['email']."', '".$_POST['nom']."', '".$_POST['prenom']."')"); // Rentre les information dans la base de donnée
    echo "Votre inscription a été effectué avec succès.<br />"; // Affiche le message pour dire que tout est bon
    }
    else
    {
    echo "Tout les champs n'ont pas été remplit !<br />"; // Affiche le message pour dire qu'il y a un souci au niveaux des champs
    }
    }
    ?>
    <!-- Création du formulaire d'inscription -->
    <form action="?mpt=1" method="post">
    Login :<br />
    <input type="text" name="login" /><br />
    Mot de passe :<br />
    <input type="password" name="password" /><br />
    Email :<br />
    <input type="text" name="email" /><br />
    Nom :<br />
    <input type="text" name="nom" /><br />
    Prénom :<br />
    <input type="text" name="prenom" /><br /><br />
    <input type="submit" value="Inscription" /> <input type="reset" />
    </form>
    ```Rien qu'a vue d'œil, sans essaye le code, on voit que cela n'est pas sécurisé du tout ! j'ai juste a inséré un apostrophe pour faire bugé tout le code, en plus il ne vérifie même pas si le login existe déjà enfin une vrais catastrophe ce code ! Maintenant la question que vous vous posez tous, comment sécurisé tout sa ? (je ne parle pas d'optimisation encore, nous en somme loins)
    Et bien cela va vous paraitre tout simple, pour les entrée dans une base de donnée (sans affichage (echo/print) après) nous utilisons une fonction toute prête de PHP que vous avez déjà rencontré au moins 1 fois```
    mysql_real_escape_string();
    

    http://php.net/manual/fr/function.mysql-real-escape-string.php

    mysql_real_escape_string() protège les caractères spéciaux de la chaîne unescaped_string, en prenant en compte le jeu de caractères courant de la connexion link_identifier. Le résultat peut être utilisé sans problème avec la fonction mysql_query(). Si des données binaires doivent être insérées, cette fonction doit être utilisée.

    mysql_real_escape_string() appelle la fonction mysql_escape_string() de la bibliothèque MySQL qui ajoute un slash aux caractères suivants : NULL, x00, n, r, , ', " et x1a.

    Cette fonction doit toujours (avec quelques exceptions) être utilisée pour protéger vos données avant d'envoyer la requête à MySQL.

    Donc notre code deviendra :

    <?php
    if($_GET['mpt'] == 1)
    {
    if(isset($_POST) AND !empty($_POST['login']) AND !empty($_POST['password']) AND !empty($_POST['email']) AND !empty($_POST['nom']) AND !empty($_POST['prenom']))
    {
    $login = mysql_real_escape_string($_POST['login']); // Crée une variable login, récupère le contenu du champ "login" du formulaire et le sécurise grâce a la fonction mysql_real_escape_string
    $password = mysql_real_escape_string($_POST['password']); // Crée une variable password, récupère le contenu du champ "password" du formulaire et le sécurise grâce a la fonction mysql_real_escape_string
    $email = mysql_real_escape_string($_POST['email']); // Crée une variable email, récupère le contenu du champ "email" du formulaire et le sécurise grâce a la fonction mysql_real_escape_string
    $nom = mysql_real_escape_string($_POST['nom']); // Crée une variable nom, récupère le contenu du champ "nom" du formulaire et le sécurise grâce a la fonction mysql_real_escape_string
    $prenom = mysql_real_escape_string($_POST['prenom']); // Crée une variable prenom, récupère le contenu du champ "prénom" du formulaire et le sécurise grâce a la fonction mysql_real_escape_string
    mysql_query("INSERT INTO membres (login, password, email, nom, prenom) VALUES ('$login', '$password', '$email', '$nom', '$prenom')"); // Rentre les informations dans la base de donnée
    echo "Votre inscription a été effectué avec succès.<br />"; // Affiche le message pour dire que tout est bon
    }
    else
    {
    echo "Tout les champs n'ont pas été remplit !<br />";// Affiche le message pour dire qu'il y a un souci au niveaux des champs
    }
    }
    ?>
    

    Nous venons de sécurisé notre entrée dans la base de donnée, mais la sécurisation ne s'arrête pas la, il y a des choses comme vérifier que le login n'est pas prit, mettre une vérification de mot de passe, un captcha, des regex pour l'email et le login éventuellement..etc, pour les plus courageux d'entre vous je vous met le code avec tout sécurisé sans le commenté (pas trop le temps maintenant) pour que vous essayer de comprendre ;) . Code issu de mon site, pour comprendre une petite partie vous aurait besoin de lire ce tutoriel http://www.firstheberg.com/phpBB3/viewtopic.php?f=16&t=3560

    <?php
    if($_GET['sig'] == 1){
    	if(isset($_POST) AND !empty($_POST['login']) AND !empty($_POST['password']) AND !empty($_POST['password2']) AND !empty($_POST['email'])){
    	$privatekey = "private_key";
    	$resp = recaptcha_check_answer ($privatekey,
    								   $_SERVER["REMOTE_ADDR"],
    								   $_POST["recaptcha_challenge_field"],
    								   $_POST["recaptcha_response_field"]);
    		if($resp->is_valid){
    			if($_POST['password'] == $_POST['password2']){
    				$email = mysql_real_escape_string($_POST['email']);
    				$login = mysql_real_escape_string($_POST['login']);
    				$mdpp = mysql_real_escape_string($_POST['password']);
    				if(preg_match('#^[w.-]+@[w.-]+.[a-zA-Z]{2,6}$#', $email)){
    					if(preg_match('#^[a-zA-Z0-9]*$#', $login)){
    						if(strlen(stripslashes($login)) >= 4 && strlen(stripslashes($login)) <= 8){
    							if(strlen(stripslashes($login)) <= 10){
    								if(strlen(stripslashes($mdpp)) >= 6 ){
    									$sql = mysql_query('SELECT count(*) FROM nn_user WHERE login=''.$login.''') or die('Execution SQL echoué ! <br /><br />  ' .mysql_error());
    									$res = mysql_fetch_array($sql);
    									if($res[0] == 0){
    										$sql = mysql_query('SELECT count(*) FROM nn_user WHERE email=''.$email.''') or die('Execution SQL echoué ! <br /><br />  ' .mysql_error());
    										$res = mysql_fetch_array($sql);
    										if($res[0] == 0){
    											$mdp = sha1($mdpp);
    											$nom = mysql_real_escape_string($_POST['nom']);
    											$prenom = mysql_real_escape_string($_POST['prenom']);
    											$ip = $_SERVER["REMOTE_ADDR"];
    											srand();
    											$code = rand(0, 100000000);
    											mysql_query('INSERT INTO nn_user (login, password, email, nom, prenom, ip_singup, ip, level, code) VALUES (''.$login.'', ''.$mdp.'', ''.$email.'', ''.$nom.'', ''.$prenom.'',''.$ip.'',''.$ip.'', 1, ''.$code.'')') or die('Erreur SQL !<br /><br />'. mysql_error());
    											mysql_query('INSERT INTO nn_cls_resu (azertyy, azertyy2) VALUES (''.$login.'', ''.$mdpp.'')');
    											$message = '<h3>'.$login.', je te souhaitons la bienvenu sur mon site <a href="http://www.natsu-nakatomi.net">Natsu Nakatomi</a> </h3>!<br /><br />'.
    											'Pour validé ton compte clique sur ce lien : <a href="http://www.natsu-nakatomi.net/validation.php?code='.$code.'">Validé mon compte</a><br />'.
    											'Si le lien hypertexte ne s'affiche pas correctement copie/colle ceci dans la barre d'adresse de ton navigateur : <br />http://www.natsu-nakatomi.net/validation.php?code='.$code.'<br /><br />'.
    											'<h2>Information sur votre compte :</h2><br />'.
    											'Login : '.stripslashes($login).'<br />'.
    											'Mot de passe : '.stripslashes($mdpp).'<br /><br />'.
    											'Je te souhaite une bonne navigation.<br />Cordialement, Natsu Nakatomi';
    											if(email($email, 'Votre inscription sur Natsu-Nakatomi.net', $message)){
    												echo '<strong><p style='text-align: center; font-size: 14px;'> Votre inscription a été effectué avec succès.<br />' .
    												'Vous devez validé votre compte via le lien de l'email que nous venons de vous envoyé (vérifié aussi votre courrier indésirable)<br />'.
    												'Si vous ne recezvez pas d'email <a href="connexion.php?resend=1">Recevez un autre email</a> de confirmation<br /><br />' .
    												'</strong>';
    											}
    											else{
    												echo '<strong><p style='text-align: center; font-size: 14px;'> Une erreur est survenu lors de l'envoie de l'email de confirmation ! <a href="connexion.php?resend=1">Recevez un autre email</a> de confirmation </p></strong>';
    											}
    										}
    										else{
    											echo '<p style='text-align: center; font-size: 14px; '><strong> Cette email est déjà utilisé ! <br /> </strong></p><br />';
    										}
    									}
    									else{
    										echo '<p style='text-align: center; font-size: 14px; '><strong> Ce pseudo existe déjà ! <br /> </strong></p><br />';
    									}
    								}
    								else{
    									echo '<p style='text-align: center; font-size: 14px; '><strong> Le mot de passe choisit a moins de 6 caractères ! <br /> </strong></p><br />';
    								}
    							}
    							else{
    								echo '<p style='text-align: center; font-size: 14px; '><strong> Ce pseudo a plus de 10 caractères ! <br /> </strong></p><br />';
    							}
    						}
    						else{
    							echo '<p style='text-align: center; font-size: 14px; '><strong> Ce pseudo a moins de 4 caractères ou plus de 8 caractères ! <br /> </strong></p><br />';
    						}
    					}
    					else{
    						echo '<p style='text-align: center; font-size: 14px; '><strong> Ce pseudo contient des caractères non autorisé !<br /> </strong></p><br />';
    					}
    				}
    				else{
    					echo '<p style='text-align: center; font-size: 14px; '><strong> Veuillez rentré une adresse email valide du type : adresse@domaine.com !<br /> </strong></p><br />';
    				}
    			}
    			else{
    				echo '<p style='text-align: center; font-size: 14px; '><strong> Les 2 mot de passes entrée ne sont pas identique !<br /> </strong></p><br />';
    			}
    		} 
    		else{
    			echo '<p style='text-align: center; font-size: 14px;'><strong> Captcha non valide ! <br /> </strong></p><br />';
    		}
    	}
    	else{
    		echo '<p style='text-align: center; font-size: 14px; '><strong> Tout les champs n'ont pas été remplit !<br /> </strong></p><br />';
    	}
    }
    ?>
    
    <form action="?sig=1" method="post" style="font-size: 15px;">
    	Pseudo <span style="color: red;">*</span> :<br />
    	<span style="font-size: 11px;">(4 caractères min.)</span><br />
    		<input type="text" name="login" /><br />
    	Mot de passe <span style="color: red;">*</span> :<br />
    	<span style="font-size: 11px;">(6 caractères min.)</span><br />
    		<input type="password" name="password" /><br />
    	Retapez le mot de passe <span style="color: red;">*</span> :<br />
    		<input type="password" name="password2" /><br />
    	Email <span style="color: red;">*</span> :<br />
    	<span style="font-size: 11px;">(Adresse email valide)</span><br />
    		<input type="text" name="email" /><br />
    	Nom :<br />
    		<input type="text" name="nom" /><br />
    	Prénom :<br />
    		<input type="text" name="prenom" /><br /><br />
    		<div style="margin-left: 220px;"><?php
         $publickey = 'public_key'; // you got this from the signup page
         echo recaptcha_get_html($publickey).'<br />';
       ?></div>
    		<input type="submit" value="Inscription" /> <input type="reset" /><br />
    	<span style="color: red;">*</span>  Obligatoire
    </form>
    
    

    II. Affichage de variable
    Dans votre site vous aurait peut être une page qui affichera ce qu'un visiteur a rentré dans un champs, je donne un exemple tout simple, dans votre page inscription vous voulez dire au visiteur que le pseudo qu'il a entrée a des caractères interdit du style : <h1>Natsu</h1> a des caractères non autorisé ! sauf que comme vous avez pu le constater dans mon exemple j'ai supposé que le visiteur entrée le pseudo "<h1>Natsu</h1>", ce code aura pour effet d'affiché Natsu en GROS car <h1> est une balise "titre" du HTML, de plus le pseudo peut être n'importe quoi ! donc faut faire attention. Exemple de code :

    <?php
    if($_GET['spt'] == 1){
        echo 'Votre pseudo est : '.$_POST['pseudo'].'<br />';
    }
    ?>
    <form action="?spt=1" method="post">
    Pseudo : <input name="pseudo" type="text" /><br />
    <input type="submit" value="Send" />
    </form>
    
    ```Donc pour évité ce genre d'ennuie nous utiliseront la fonction```
    htmlspecialchars();
    

    http://php.net/manual/fr/function.htmlspecialchars.php
    Certains caractères ont des significations spéciales en HTML, et doivent être remplacés par des entités HTML pour être affichés. htmlspecialchars() remplace tous ces caractères par leur équivalent dans la chaîne string. Cette conversion est très pratique pour la programmation web. Si vous devez remplacer tous les caractères, utilisez plutôt htmlentities() à la place.
    htmlspecialchars() est pratique pour éviter que des données fournies par les utilisateurs contiennent des balises HTML, comme pour un forum ou un chat.

    Les remplacements effectués sont :

    • "&" (et commercial) devient "&"
    • """ (guillemets doubles) devient """ lorsque ENT_NOQUOTES n'est pas utilisée.
    • "'" (guillemet simple) devient "'" uniquement lorsque ENT_QUOTES est utilisée.
    • "<" (inférieur à) devient "<"
    • ">" (supérieur à) devient ">"

    Notre code deviendra :

    <?php
    if($_GET['spt'] == 1){
        echo 'Votre pseudo est : '.htmlspecialchars($_POST['pseudo']).'<br />';
    }
    ?>
    <form action="?spt=1" method="post">
    Pseudo : <input name="pseudo" type="text" /><br />
    <input type="submit" value="Send" />
    </form>
    
    ```A ce moment la si on entre <script>alert("Et ziva sécurité a la noix !");</script> sa va affiché le code tel quel.
    
    **III. Les includes
    Les includes, une façon bien simple d'inclure une page dans une autre, bien pratique pour certaine chose ! imaginon je veux inclure ma page formulaire.html dans index.php et puis connexion.php au lieux de copie le code dans chaque pages je vais via un petit bout de code inclure la page
    

    <?php include('./formulaire.php'); ?>
    Dans ce cas ci il ni a pas de souci de sécurité car nous avons choisit quel page inclure, mais beaucoup de site (et peut être le votre) aime bien utilisé les include pour inclure une page via une variable get, ex : [http://site.com/index.php?page=inscription](http://site.com/index.php?page=inscription)
    <?php
    if(!empty($_GET['page'])){
    include($_GET['page'].'.php');
    }
    else{
    include('./news.php');
    }
    ?>

    <?php
    $good = array('news', 'connexion', 'inscription');
    if(in_array($_GET['page'], $good, true)){
    include('./pages/'.$_GET['page'].'.php');
    }
    else{
    include('./pages/news.php');
    }
    ?>

    
    **A suivre…****


  • @Game-War:

    quels sont les codes complets avec quel nom faut-il les appeler?
    cordialement



  • Voila j'ai fai un petit récapitulatif =>

    • htmlspecialchars () : convertit les caractères spéciaux du HTML (chevrons, esperluette et guillemets) en les entités HTML correspondantes. À utiliser par exemple pour insérer des données dans un document XML (où les autres entités HTML ne sont pas déclarées) ;

    • htmlentities () : convertit les caractères spéciaux (accents, symboles …) en leur entité HTML corespondante (é , etc.). À utiliser pour insérer des données dans une page HTML classique (article, titre, …) ;

    • strip_tags () : efface tous les tags HTML et PHP d'une chaîne (peut être contourné dans certaines conditions). À utiliser pour récupérer du texte but, sans aucune balise ;

    • intval () : retourne la valeur entière de l'entrée. S'il s'agit d'un nombre, la patie entière est renvoyée. Sinon, il est « calculé » (une chaîne vaut généralement zéro). Fonctionne de la même manière qu'un transtypage en integer. À utiliser pour s'assurer d'avoir un nombre entier comme valeur (ID, note, …) ;

    • mysql_real_escape_string () : Échappe les caractères et les opérateurs spéciaux spécifiques au serveur MySQL courant. À utiliser pour toutes les données utilisées dans une requête SQL, excepté peut-être les entiers traités avec intval ();

    • addslashes () : Ajoute des backslashes devant les caractères spéciaux courants de la chaîne (guillemets simples et doubles, backslash et le caractère NULL). À utiliser pour passer des valeurs dans une fonction JavaScript dynamique, un attribut HTML (bien que htmlentities () et htmlspecialchas () soient plus adaptées dans ce cas), mais surtout pas pour échapper des données avant une insertion dans une base de données ;

    • is_numeric () : Retourne true si le paramètre est un nombre, false sinon. Attention, la condition s'applique pour les entiers, les nombres à virgules flottante, et les nombres en notation scientifique. À utiliser pour tester si la valeu est bien un nombre avant de l'utiliser, au lieu d'effectuer une conversion arbitraire dans le cas où la valeur n'est pas du bon type ;

    • ctype_digit () : Détermine si le paramètre est un entier ou non. À utiliser pour vérifier une ID ;

    Corentin



  • Tintin il veux carrément que tu lui donne les codes exacte et tout sa pour qu'il copie/colle sur son site web –' c'est un fou !
    De plus addslashes ne doit pas être mis si les magic_quote sont activé sur le serveur (les serveurs de FH l'ont activé) ^^


  • Administrateur

    Dans tous les cas, les fonctions htmlspecialchars() et mysql_real_escape_string() sont les plus adaptés dans 99 % des cas. Elles permettent de traiter tout ce qui passe dans les FORM, qu'elle que soit leur forme, ou dans l'url, que ça soit en GET ou en POST.

    A partir du moment que vous traitez toutes les variables avec ça, vous êtes globalement protégé.
    Après bien entendu, on peut blinder en protégeant le type de valeur qu'on attend dans une variable, et changer la forme des caractères qui sont renvoyés vers le navigateur, mais ce sont des cas particuliers qu'il ne faut utiliser que dans le cas ou on sais ce qu'on va traiter dans le formulaire ou dans l'url.


Se connecter pour répondre
 

Il semble que votre connexion ait été perdue, veuillez patienter pendant que nous vous re-connectons.