Précédent   Forum des professionnels en informatique > PHP > Langage > Sessions
Sessions Forum d'entraide sur les sessions avec PHP. Avant de poster -> FAQ sessions, Cours sessions et Sources sécurité
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 12/09/2006, 00h31   #1
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Par défaut [Sécurité] Comment sécuriser un champ textarea ?

Bonjour,

Je dois sécuriser un formulaire.
Pour certains champs je sais le type de données attendues, donc c'est très bien j'utilise les expregs.
Mais pour le textarea, je ne sais pas ce que l'on peut m'envoyer et je ne peux pas interdire de caractères.

Donc comment le filtrer au mieux ?
Je peux faire ça :
Code :
htmlentities(mysql_real_escape_string($textarea))
Mais est-ce suffisant et sinon que faire d'autre ?

Merci de votre aide
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 10h21   #2
Membre du Club
 
Inscription : janvier 2006
Messages : 79
Détails du profil
Informations personnelles :
Âge : 25

Informations forums :
Inscription : janvier 2006
Messages : 79
Points : 54
Points : 54
Salut,

tu veux le sécuriser contre quoi (certains mots,...) ?
druidev est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 10h33   #3
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Non contre les attaques xss, injections sql et autres joyeusetés. Les mots doivent rester libres et je ne peux pas bloquer les caractères spéciaux.
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 10h44   #4
Membre Expert
 
Homme
Inscription : janvier 2004
Messages : 1 238
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : janvier 2004
Messages : 1 238
Points : 1 421
Points : 1 421
alors...

si tu veux faire un bon filtrage :

1)
* Verifier en php le reglage des magicquotes (avec get_magic_quotes_gpc())
* Si activé alors stripslashes sur la variable

=> Tu obtiens dorenavant un champ qui correspond exactement a ce que l'utilisateur a tapé !!

Ensuite, le traitement a faire depend de l'utilisation :

2)
* pour inserer dans une base de données :
mysql_real_escape_string
* pour afficher sous forme de texte :
htmlentities
* pour afficher dans un value de formulaire ou un autre attribut d'une balise html :
addslashes

Ensuite, ton traitement est sécurisé... a condition que :
* dans toutes les requetes qui travaillent sur le champs utilisé pour stocker l'info tu utilise des quotes autour du champs : SELECT ... champ = '$champ', etc...
* chaque fois que tu récupere l'info depuis la base, tu dois refaire le traitement en fonction de l'utilisation a partir du point 2

Dans la pratique, je te conseille de tester TOUT tes champs avec le crash test suivant :
Code :
a'a"a/a\a<b>a</b>a<br>a
si cette chaine se réaffiche exactement telle qu'elle a été tapée partout sans faire aucune erreur, il y a de grande chance que ton code soit a peu pres correct ;o)
(et quand je dis exactement, c'est exactement ! pas de \ en trop, pas de \ en moins, pas de "a" en gras ou de retour chariot interprété avec <br>, et les tests sont a faire en affichage, creation, modification et suppression de ton objet)

Je crois que j'ai fait le tour, j'ai oublié qqchose ? ;o))
__________________
PHP :
Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production)
Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error());
Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable.
Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/
Fladnag est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 11h42   #5
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
salut Fladnag, merci pour cette réponse complète.

Alors une question déjà :

Citation:
Ensuite, ton traitement est sécurisé... a condition que :
* dans toutes les requetes qui travaillent sur le champs utilisé pour stocker l'info tu utilise des quotes autour du champs : SELECT ... champ = '$champ', etc...
Je fais ça :
Code :
SELECT...champ='.$champ.'
ça revient au même, qu'est ce que t'en pense ? Et au fait, pourquoi les quotes sont un support contre les injections sql ?

Sur un autre post, j'ai lu cette phrase :
Citation:
D'ailleurs, faire un "mysql_real_escape_string" sur une variable placé directement dans une requête sans apostrophe n'empêche pas le "piratage".
ça semble confirmer. Mais alors pourquoi mysql_real_escape_string() + apostrophes dans la requête = sécurité et pourquoi sans les apostrophes ça ne l'est plus ?
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 12h42   #6
Membre Expert
 
Homme
Inscription : janvier 2004
Messages : 1 238
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : janvier 2004
Messages : 1 238
Points : 1 421
Points : 1 421
Citation:
Envoyé par JackBeauregard
Je fais ça :
Code :
SELECT...champ='.$champ.'
ça revient au même, qu'est ce que t'en pense ? Et au fait, pourquoi les quotes sont un support contre les injections sql ?
C'est justement ce qu'il faut eviter ;o)

Code :
1
2
3
SELECT ... champ=\''.$champ.'\'....
ou 
SELECT ... champ='".$champ."'...
est correct.

ta requete va construire :
donc imaginons une requete :
Code :
SELECT * FROM membres WHERE login=$login AND password=$password
maintenant, je rentre comme login : $login="admin--"

la requete devient :
Code :
SELECT * FROM membres WHERE login=admin-- AND password=
manque de bol pour toi, -- veux dire que le reste de la ligne de la requete SQL est un commentaire... donc on ne fait aucune verification sur le mot de passe !

Si tu met des quotes, tu obtient comme requete :
Code :
SELECT * FROM membres WHERE login='admin--' AND password=''
et là mysql va bien comprendre que c'est la chaine "admin--" qu'il faut verifier.

Ce n'est qu'un exemple de ce qui est possible. Si le sujet t'interesse, je te conseille de lire les articles sur l'injection sql disponible sur ce site : http://www.phpsecure.info/v2/zone/pArticle
ce n'est pas un panel exhaustif de ce qui est possible, mais c'est une tres bonne introduction, et ca permet en principe de se rendre compte de la fragilité d'un script php mal codé ;o)
__________________
PHP :
Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production)
Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error());
Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable.
Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/
Fladnag est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 12h51   #7
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Je vais voir ton lien, merci pour tes explications.

J'ai revérifié mon code, mes requêtes sont comme ça :
Code :
$requete="SELECT descriptionFROM complements WHERE id = '".$id."' ";
Peux-tu me confirmer que cela c'est bon, s'il te plait ?

Aussi j'en ai une comme ça, et là je n'arrive pas à la placer entre '".."' :
Code :
"SELECT libelle    FROM definitions WHERE mot like '$lettre%' ";
Celle là j'ai essayé ça '".$lettre.%"' ou '".$lettre"'% mais ça fait foirer ma requête.
En plus $lettre peut contenir des lettres ou le signe - donc au vu de ton exemple même une expreg, qui n'autorise que des lettres et le trait d'union, ne servirait à rien.
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 12h58   #8
Rédacteur
 
Avatar de Yogui
 
Homme Guillaume Rossolini
Directeur technique
Inscription : février 2004
Messages : 13 720
Détails du profil
Informations personnelles :
Nom : Homme Guillaume Rossolini
Localisation : France

Informations professionnelles :
Activité : Directeur technique

Informations forums :
Inscription : février 2004
Messages : 13 720
Points : 17 355
Points : 17 355
@Fladnag : addslashes() n'est jamais utile car si tu envoies tes données dans une page HTML, alors il est préférable d'utiliser htmlentities() avec son deuxième paramètre ENT_QUOTES.

[Edit] Au passage :
http://securite.developpez.com/faq/?..._sql_injection
__________________
Mes articles - Zend Certified Engineer (PHP + Zend Framework)
Ressources PHP - Ressources Zend Framework
Yogui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 13h34   #9
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Bon dans le même genre parce que je ne vais pas ouvrir un sujet que pour ça, j'ai le problème ci-dessous :

Requête :
Code :
1
2
3
4
FROM commentaire 
WHERE idDef='".$idDef."' 
ORDER BY timeDernierSousCom  DESC 
LIMIT ".$debut.",".$fin."";
Donc ici ça fonctionne bien.

Par contre :
Code :
1
2
3
4
FROM commentaire 
WHERE idDef='".$idDef."' 
ORDER BY timeDernierSousCom  DESC 
LIMIT '".$debut."','".$fin."'  ";
Là j'ai une erreur déclenché par les simples quotes. Mais ailleurs ça fonctionne bien, comme dans la clause WHERE avec $idDef.

Donc pourquoi ça rate pour les deux autres (à tout hasard je précise que $debut et $fin sont des chiffres entier).
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 14h03   #10
Membre chevronné
 
Inscription : mars 2005
Messages : 583
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 583
Points : 651
Points : 651
hello,

lorsque tu utilises des entiers dans tes requetes, les apostrophes sont inutiles (voir meme déconseillées, si quelqu'un peut confirmer ?)

dans la clause LIMIT en l'occurence, elles font meme planter la requete.
Petibidon est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 14h22   #11
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Oui mais pourtant j'ai une autre requête où j'utilise un entier et ça ne foire pas en le placant comme suit :'".$entier."'

Dans mon exemple au dessus, ça ne viendrait pas de la clause LIMIT ?
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 14h33   #12
Rédacteur
 
Avatar de Yogui
 
Homme Guillaume Rossolini
Directeur technique
Inscription : février 2004
Messages : 13 720
Détails du profil
Informations personnelles :
Nom : Homme Guillaume Rossolini
Localisation : France

Informations professionnelles :
Activité : Directeur technique

Informations forums :
Inscription : février 2004
Messages : 13 720
Points : 17 355
Points : 17 355
Petibidon vient de te dire que c'est le cas, en effet.
@Petibidon : Tout dépend... Si tu sais que tu protègeras toujours tes valeurs entières, alors il est préférable de ne pas mettre de quotes puisque cela permet au SGBD de traiter correctement le type de la donnée. Sinon, peut-être que les quotes sont un moindre mal (mais pas une solution).
__________________
Mes articles - Zend Certified Engineer (PHP + Zend Framework)
Ressources PHP - Ressources Zend Framework
Yogui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 15h06   #13
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Citation:
Petibidon vient de te dire que c'est le cas, en effet.
Oui mais j'ai pas assez dormi aujourd'hui alors hein...



Bon dans la série des questions crétines, puisque ça semble être le jour, en voilà encore une :

A réception des données de l'url je fais ça pour tester le masque :
Code :
1
2
if(preg_match('/^[a-z]+$/',$_GET['definition']))//accepte lettres et trait d'union
{$definition=mysql_real_escape_string(htmlentities($_GET['definition']));}
Mais en plus à divers endroit des scripts qui sont inclus dans la page initiale, j'ai des requêtes et je refais avant :
Code :
$definition=mysql_real_escape_string(htmlentities($definition))
ça sert à rien vous allez me dire, pas vrai ? J'avais dû faire ça parce que les requêtes étaient placées dans des fichiers requis.
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 15h26   #14
Rédacteur
 
Avatar de Yogui
 
Homme Guillaume Rossolini
Directeur technique
Inscription : février 2004
Messages : 13 720
Détails du profil
Informations personnelles :
Nom : Homme Guillaume Rossolini
Localisation : France

Informations professionnelles :
Activité : Directeur technique

Informations forums :
Inscription : février 2004
Messages : 13 720
Points : 17 355
Points : 17 355
Peut-être suis-je également fatigué mais il me semble t'avoir déjà dit (et je ne suis pas le seul) que ces deux fonctions n'ont pas la même utilité. Il ne faut pas les utiliser conjointement car c'est une erreur de logique.
__________________
Mes articles - Zend Certified Engineer (PHP + Zend Framework)
Ressources PHP - Ressources Zend Framework
Yogui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 15h34   #15
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Bah la question portait pas sur ça, mais bon c'était une fausse question de toute façon. Je voulais savoir si le pirate pouvait modifier une variable en cours de scripts.
On va marquer résolu...

Merci à tous
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 15h47   #16
Rédacteur
 
Avatar de Yogui
 
Homme Guillaume Rossolini
Directeur technique
Inscription : février 2004
Messages : 13 720
Détails du profil
Informations personnelles :
Nom : Homme Guillaume Rossolini
Localisation : France

Informations professionnelles :
Activité : Directeur technique

Informations forums :
Inscription : février 2004
Messages : 13 720
Points : 17 355
Points : 17 355
En cours de script ? Bien sûr que non : chaque action de l'utilisateur déclenche une exécution de script mais l'utilisateur ne peut pas intervenir pendant ce procesus.
__________________
Mes articles - Zend Certified Engineer (PHP + Zend Framework)
Ressources PHP - Ressources Zend Framework
Yogui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 15h57   #17
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Donc je filtre une fois à réception de la variable $_GET['var'], et c'est bon pour toutes les requêtes de la page y compris celles situées dans des fichiers requires.
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 16h07   #18
Rédacteur
 
Avatar de Yogui
 
Homme Guillaume Rossolini
Directeur technique
Inscription : février 2004
Messages : 13 720
Détails du profil
Informations personnelles :
Nom : Homme Guillaume Rossolini
Localisation : France

Informations professionnelles :
Activité : Directeur technique

Informations forums :
Inscription : février 2004
Messages : 13 720
Points : 17 355
Points : 17 355
S'il s'agit d'une valeur numérique, il suffit de filtrer une fois au départ pour pouvoir utiliser la variable dans les requêtes et pour l'envoyer dans le HTML.
S'il s'agit d'une variable texte, il faut la filtrer pour chaque utilisation, avec la fonction qui va bien.
  • mysql_real_escape_string() pour une requête MySQL ;
  • htmlentities() avec ses 3 paramètres pour le HTML ;
  • preg_quote() pour une regex ;
  • etc.
Je suis en train de finaliser un article qui résume tout cela.
__________________
Mes articles - Zend Certified Engineer (PHP + Zend Framework)
Ressources PHP - Ressources Zend Framework
Yogui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 16h47   #19
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Ton article sera le bienvenue Yogui, merci d'avance pour celui-ci.

Citation:
S'il s'agit d'une valeur numérique, il suffit de filtrer une fois au départ pour pouvoir utiliser la variable dans les requêtes et pour l'envoyer dans le HTML.
S'il s'agit d'une variable texte, il faut la filtrer pour chaque utilisation, avec la fonction qui va bien.
Bon alors je suis de nouveau embrouillé. Parce que plus haut tu dis :
Citation:
En cours de script ? Bien sûr que non : chaque action de l'utilisateur déclenche une exécution de script mais l'utilisateur ne peut pas intervenir pendant ce procesus.

Dans mon cas je reçois deux types de variables par l'URL, une numérique et une texte + tiret ou texte seul (exemple : "mot-nouveau" ou "mot" avec que des lettres dans les deux cas).
J'ai donc ces deux preg_match pour vérifier le masque :

Code :
1
2
3
4
5
6
7
8
 
//on vérifie si on a un chiffre
if(preg_match('/^[0-9]/',$_GET['chiffre']))
{$chiffre=intval($_GET['chiffre']);} 
 
//on vérifie si on des lettres
if(preg_match('/^[a-z]+$/',$_GET['definition']))
{$definition=mysql_real_escape_string($_GET['definition']);}
Dans les deux cas, les variables sont utilisées pour plusieurs requêtes à l'intérieur de la page.
Donc si je suis ce que tu dis dans ta dernière réponse, le gars pourrait trafiquer en cours de page $definition mais ne pourrait le faire avec $chiffre ?


**edit** le coup du intval($chiffre) après avoir vérifié par expreg que l'on a des chiffres est un peu inutile... mais là je suis pas encore sur ça, c'est pas comme ça dans mon script. Et si on a qu'une lettre, est-ce tout de même du texte et qu'est-ce que ça change par rapport à la question qui nous préoccupe à savoir la modification des données en cours de page selon que la variable est numérique ou que sa valeur est un texte ?
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2006, 16h55   #20
Rédacteur
 
Avatar de Yogui
 
Homme Guillaume Rossolini
Directeur technique
Inscription : février 2004
Messages : 13 720
Détails du profil
Informations personnelles :
Nom : Homme Guillaume Rossolini
Localisation : France

Informations professionnelles :
Activité : Directeur technique

Informations forums :
Inscription : février 2004
Messages : 13 720
Points : 17 355
Points : 17 355
Il faut bien voir que l'utilisateur fait simplement une demande de page Web identifée par une URI et contenant éventuellement des données en GET, POST et/ou COOKIE. Au-delà, l'utilisateur ne peut pas faire grand chose à part attendre la réponse du serveur.
Durant toute l'exécution du script, ton internaute n'a absolument aucun contrôle sur ce qu'il se passe. Du coup, à mon sens, il ne peut pas agir "au milieu" de l'exécution. De mon point de vue, toutes les variables soumises par l'utilisateur doivent être filtrées une première fois au départ du script puis, selon le cas, lors de leur utilisation.

Chris Shiflett recommande l'utilisation de tableaux :
Code :
1
2
3
4
5
6
7
8
$mysql = array();
$mysql['username'] = mysql_real_escape_string($_POST['username']);
$mysql['password'] = md5($_POST['password']);
 
$html = array();
$html['username'] = htmlentities($_POST['username'], ENT_QUOTES, 'ISO-8859-1');
 
unset($_POST);
__________________
Mes articles - Zend Certified Engineer (PHP + Zend Framework)
Ressources PHP - Ressources Zend Framework
Yogui est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 16h54.


 
 
 
 
Partenaires

Hébergement Web