8768 sujets

Développement web côté serveur, CMS

Bonjour à tous.

Dans le cadre d'un projet en cours, j'ai développé plusieurs formulaires tous gérés par un seul fichier PHP.

J'utilise PDO et les requêtes préparées donc je m'inquiète moins pour les injections que pour les attaques de types XSS. J'ai un peu lu sur le net mais j'ai lu tout et son contraire et je voudrais une vision "à jour" de ce problème.

Je vous poste donc une partie du code, sachant qu'à chaque fois le principe est le même pour chaque formulaire. SI vous avez des conseils ça sera avec plaisir.

En vous remerciant d'avance :

if(isset($_POST['action']))
	{
		switch ($_POST['action']) 
			{
			case 'inscription':

				// préparation des données pour l'insertion
				$tableau= array($_POST['civilite'], $_POST['nom'], $_POST['prenom'], $_POST['email'], $_POST['telephone'],$_POST['cp'],
				$_POST['ville'], $_POST['login'],md5($_POST['password']),$_SERVER['REMOTE_ADDR'],date('Y-m-d'),date('Y-m-d'));
				
				//Variables et requête pour vérification de l'adresse email et du login
				$email = $_POST['email'];
				$login = $_POST['login'];
			        $check="SELECT email,login FROM membre WHERE email LIKE '".$email."' OR login LIKE '".$login."'";
				$res = $connexion->query($check);
	
				// si un résultat est trouvé, on affiche un message d'erreur.
				if($res->rowCount() !=0)
				{
					$smarty = new Smarty();
					$smarty->assign('email',$email);
					$smarty->assign('login',$login);
					$smarty->display("{$base_dir}/html/inscription_NOK.html");	
				}
				//sinon on insére les données dans la base de données
				else
				{
					try {
						// Requête préparée
						$prepa = $connexion->prepare("INSERT INTO membre (civilite,nom,prenom,email,telephone,code_postal,ville,login,pass,ip,lastvisite,date_inscription) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)");
						// exécution de la requête
						$prepa->execute($tableau);
						// Création d'un objet Smarty
						$smarty = new Smarty();
						//variables pour le message de confirmation
						$smarty->assign(array('nom' => $_POST ['nom'],'prenom' => $_POST ['prenom']));
						// affichage de la confirmation d'inscription
						$smarty->display("{$base_dir}/html/inscription_OK.html");
					
						}
						// affichage d'un message d'erreur si l'insertion n'a pas fonctionné
					catch (PDOException $erreur)
						{
							$smarty = new Smarty();
							$smarty->display("{$base_dir}/html/error.html");
						}
				}		
			break;
         }
}
Salut,
je ne connais pas trop le modèle PDO, mais je pige pas bien comment ça te protège d'injection sql :s.
Je suis pas un expert dans les injections et loin d’être imaginatif pour montrer une grosse faille, mais j'ai l'impression que si par exemple l'email vaut "';-- on arrive à passer a travers le test de vérification de 0 lignes. (J'avoue que je n'ai pas trop idée de ce que cela ferait sur le insert qu'il y a ensuite, mais bon quelqu'un qui s'y connait pourrait sans doute faire des trucs intéressants ^^ )


Je pense qu'il faut utiliser ça : http://www.php.net/manual/fr/mysqli.real-escape-string.php

et eventuellement http://fr.php.net/htmlentities ou http://fr.php.net/manual/fr/function.htmlspecialchars.php selon ce que tu fais de tes données ensuite.
shupi tu ne donnes pas assez d'infos sur ce dont tu veux te protéger et dans quel contexte.

mathieu1004 a écrit :

je ne connais pas trop le modèle PDO, mais je pige pas bien comment ça te protège d'injection sql :s.


Ce n'est pas PDO qui protège des injections mais l'utilisation de requêtes préparées.

mathieu1004 a écrit :

Je suis pas un expert dans les injections et loin d’être imaginatif pour montrer une grosse faille, mais j'ai l'impression que si par exemple l'email vaut "';-- on arrive à passer a travers le test de vérification de 0 lignes. (J'avoue que je n'ai pas trop idée de ce que cela ferait sur le insert qu'il y a ensuite, mais bon quelqu'un qui s'y connait pourrait sans doute faire des trucs intéressants ^^ )


Complètement à côté. Smiley langue

mathieu1004 a écrit :

Je pense qu'il faut utiliser ça : http://www.php.net/manual/fr/mysqli.real-escape-string.php


Pas du tout, la méthode du shupi est bien meilleure et en plus tu montres une fonction pour mysqli alors qu'il utilise PDO.

mathieu1004 a écrit :

et eventuellement http://fr.php.net/htmlentities ou http://fr.php.net/manual/fr/function.htmlspecialchars.php selon ce que tu fais de tes données ensuite.



Euh... rien à voir.
Le select quant à lui n'est pas protégé (voir query):

$check="SELECT email,login FROM membre WHERE email LIKE '".$email."' OR login LIKE '".$login."'";
$res = $connexion->query($check);
Donc du coup je transforme ça en

$check="SELECT email,login FROM membre WHERE email LIKE ".$connexion->quote($email)." OR login LIKE ".$connexion->quote($login);

$res = $connexion->query($check);


Sinon pour te répondre jb_gfx, n'étant pas un expert dans le domaine j'ai soumis mon formulaire à un ami un peu plus calé et qui me montrait qu'à l'aide d'une page externe et de CURL notamment, il arrivait à insérer des données incorrectes dans certains champs de ma table.

Merci pour la suite des réponses et pour les conseils
Tu ne fais pas vraiment de vérification sur tes données en même temps.
Qu'entends tu par des "données incorrectes" que ton ami a pu insérer?
Oui tu peux faire comme ça, perso je serai parti sur des requêtes préparées comme tu as fait plus bas.
Donc un truc du genre ?

$data = array($email,$login);

$check="SELECT email,login FROM membre WHERE email LIKE ? OR login LIKE ?;
$check= $connexion->execute($data);


Sinon je vérifie les différents champs de mon formulaire à la saisie avec des regexp javascript, mais il arrive à outrepasser celles-ci
shupi a écrit :
Sinon je vérifie les différents champs de mon formulaire à la saisie avec des regexp javascript, mais il arrive à outrepasser celles-ci


ähm, autant c'est bien de faire des vérifications côté client autant côté serveur c'est indispensable ! Repense à ce que fais ton ami, d'après toi il a du JS via CURL? Donc fais tes vérifications côté serveur.

Regarde la doc et fais des tests, il n'y a que comme ça que tu apprendras Smiley smile
Modérateur
Bonjour,

La règle d'or est de ne jamais faire confiance aux données qui proviennent de l'utilisateur, que ce soit les champs des formulaires, les variables dans l'url, les cookies, etc... Un utilisateur peut facilement modifier les données envoyées au serveur, le code HTML de la page, désactiver le Javascript ou en modifier le comportement dans son navigateur, et ainsi de suite.
shupi a écrit :
Donc du coup je transforme ça en

$check="SELECT email,login FROM membre WHERE email LIKE ".$connexion->quote($email)." OR login LIKE ".$connexion->quote($login);

$res = $connexion->query($check);



Tu peux utiliser la méthode quote() (qui est équivalente à mysqli_real_escape_string) mais puisque que tu es parti dans l'idée d'utiliser des requêtes préparées tu devrais t'y tenir et les utiliser partout plutôt que de mixer quote() et requêtes préparées.

Et comme ça a été dit tu dois valider tes données coté serveur, c'est absolument obligatoire. En PHP tu peux utiliser la fonction filter_var et ses différents filtres et les expressions rationnelles avec preg_match (filter_var en priorité, preg_match si tu trouves pas le filtres que tu veux).

http://www.php.net/manual/fr/function.filter-var.php
http://www.php.net/manual/fr/function.preg-match.php
Modifié par jb_gfx (17 Feb 2014 - 21:09)
Oula j'avais pas vu, j'aime bien comment il a complétement démonter mon message Smiley lol
( alors que il y avait une toute petite part de vrai Smiley fache )