fonction de protection

Eléphant du PHP | 259 Messages

01 juin 2007, 17:01

bonjour

pour mon site, je n'ai qu'une seule page : la page index

les autres sont appelées sous la forme http://www.www/index.php?page=accueil
après je vais chercher dans bdd l'adresse ou se trouve la page a inclure

et elle est incluse un peu plus loin , dans la présentation du site, dans un tableau

pour éviter que des gens mal-intentionnés essayent de passer des codes malveillants, j'ai créé une fonction de protection

je fais un $_GET puis je passe sa dans la fonction qui me retourne la nom de la page "protégé"
puis requête sql ...

voici ma fonction :
qu'en pensez vous ?
si vous pouviez me donner des petites astuces pour augmenter la sécurité de mon site je vous remercie d'avance

note : toutes les variables passées en $_GET et $_POST passent dans une fonction de protection similaire mais qui accepte plus de caractères
$page=$_GET['page'];			// on recupere la page desiree
include"......."; // fichier des fonctions
$page=protect1($page);

if(empty($page))
{
$page="index";
}

// puis requête et stratégie de sécurité ( si il faut une session ...
function protect1 ($entree) 
{ 
	$entree = str_replace("#", "",$entree) ;  // quelques remplacements
	$entree = str_replace("<", "",$entree) ;
	$entree = str_replace(">", "",$entree) ;
	$entree = htmlspecialchars($entree, ENT_QUOTES);
	$entree = htmlentities($entree, ENT_QUOTES);
	$entree = strtr($entree,"ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ","AAAAAAaaaaaaOOOOOOooooooEEEEeeeeCcIIIIiiiiUUUUuuuuyNn");
	$entree = substr("$entree", 0, 40);  // on coupe a 40 caractères au cas ou
	$entree = mysql_real_escape_string($entree); 
	$entree = stripslashes($entree);
    return ($entree);
}
voila

merci bien
l'hébergeur gratuit que j'utilisais: http://www.freeheberg.com (pas de limitte de débit, BP, 1à10Go, bdd mysql illimitées )
mainteant je suis chez OVH, payant mais plus adapté à de gros sites

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

02 juin 2007, 10:46

Bonjour,

A mon avis les solution les + simples sont souvent les meilleures:
$tablo_pages_autorisees=array("nom_page1", "nom_page2");
$page_demandee=$_GET['page'];

if (in_array($page_demandee,$tablo_pages_autorisees)) {
     $page=$page_demandee;
}else{
     $page="index";
}
Quand tout le reste a échoué, lisez le mode d'emploi...

Eléphant du PHP | 259 Messages

02 juin 2007, 11:04

oui mais cette fonction sert aussi a filtrer les posts de formulaires ...

je vais faire ceci pour les pages, en effet c'est plus pratique mais sinon pour le reste je cherche a améliorer cette fonction

merci
l'hébergeur gratuit que j'utilisais: http://www.freeheberg.com (pas de limitte de débit, BP, 1à10Go, bdd mysql illimitées )
mainteant je suis chez OVH, payant mais plus adapté à de gros sites

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

02 juin 2007, 11:33

Elle ressemble pas à grand chose ta fonction :/ Un htmlspecialchars() suivi d'un htmlentities(), un mysql_real_escape_string() suivi d'un stripslashes(), une coupure arbitraire à 40 caractères, tout ceci semble plus «étrange» que réellement utile.

Eléphant du PHP | 259 Messages

02 juin 2007, 12:21

c'est ce que j'ai réussit à faire pour empecher de passer des codes malveillants par formulaires ...

c'est déjà mieux que de rien filtrer

si vous avez des idées, n'hésitez pas

merci
l'hébergeur gratuit que j'utilisais: http://www.freeheberg.com (pas de limitte de débit, BP, 1à10Go, bdd mysql illimitées )
mainteant je suis chez OVH, payant mais plus adapté à de gros sites

Eléphant du PHP | 199 Messages

02 juin 2007, 13:21

Heu... pas besoin d'un lance-roquette pour tuer un lapin...

Pour entrer des informations en base de données et éviter les injections SQL, tu utilises la fonction d'échappement correspondant à ta base de données mysql_real_escape_string(), par exemple, ou la méthode quote() de PDO si tu utilises la couche d'abstraction. Ou même éventuellement addslashes(), ça marche aussi (enfin je crois).

Après à l'affichage, il convient d'empêcher l'affichage de code HTML (et JS), et là tu as le choix :
- htmlspecialchars() si tu veux juste empêcher que les balises HTML soient interprêtées comme telles
- strip_tags() si tu veux carrement supprimer les balises HTML (tu peux indiquer les balises que tu veux autoriser en 2ème paramètre de cette fonction)

Je crois que c'est suffisant pour contrôler les données venant des formulaires. Après à toi de contrôler au cas par cas le type de données transmises en fonction du contexte (texte, nombre entier, tableau, fichier...).

Après pour le système de pages effectivement le plus simple c'est d'utiliser un tableau ou pourquoi pas de stocker tes pages dans un dossier et de les inclure si le fichier existe avec file_exists().

PS : Le tout avec la directive magic_quotes_gpc du php.ini à Off
Klomac - Blog Lambda

Eléphant du PHP | 259 Messages

02 juin 2007, 14:29

euh

j'ai vu sur internet qu'il fallait mettre magic_quotes a on sinon les ' et les " ne sont pas echapés,

et si une personne mal intentionnée arrive a passer sa dans une de mes requêtes
va y avoir du dégat ( http://www.phpsecure.info/v2/article/InjSql.php )

sinon merci pour tes conseils

je voulais savoir, le mysql_real_escape_string() je dois le mettre où ?
avant la connection bdd, juste après, avant chaque requête ... ???

merci
l'hébergeur gratuit que j'utilisais: http://www.freeheberg.com (pas de limitte de débit, BP, 1à10Go, bdd mysql illimitées )
mainteant je suis chez OVH, payant mais plus adapté à de gros sites

Eléphant du PHP | 199 Messages

02 juin 2007, 14:54

Concernant les magic_quotes, c'est à la base censé te prémunir, car les apostrophes et les guillemets sont automatiquement échappés dans les données venant des formulaires.

Le soucis c'est que dans ce cas tu dois faire la distinction entre les données utilisateurs venant des formulaires, et les autres pour savoir ce que tu dois échapper et ce que tu ne dois pas.

Le plus sûr c'est de considérer que les données utilisateurs, venant de formulaires ou non, doivent toujours être échappées par tes soins. D'où les magic_quotes désactivées. Qui plus est, cette fonction ne sera pas disponible dans PHP6, donc autant prendre les bonnes habitudes tout de suite.

Donc la méthode à appliquer quand tu traite des données utilisateurs :
- avant de les mettre dans la base de données, tu appliques la fonction d'échappement correspondant à ta base de données (donc mysql_real_escape_string, par exemple, avant d'effectuer ta requête)
- avant de les afficher, tu supprimes éventuellement le HTML
Klomac - Blog Lambda

Eléphant du PHP | 259 Messages

02 juin 2007, 15:24

ok merci

mais a votre avis, dois-je utiliser le maximum de fonctions au cas où, ou juste la meilleur

par exemple
	// suppression des balises html et des caractères spéciaux
	$entree = strip_tags($entree);
	$entree = htmlspecialchars($entree, ENT_QUOTES);
	$entree = htmlentities($entree, ENT_QUOTES);
et pour
	$entree = addslashes($entree);
	$entree = mysql_real_escape_string($entree);
est ce que celà rajoute deux fois \ ???
l'hébergeur gratuit que j'utilisais: http://www.freeheberg.com (pas de limitte de débit, BP, 1à10Go, bdd mysql illimitées )
mainteant je suis chez OVH, payant mais plus adapté à de gros sites

Eléphant du PHP | 199 Messages

02 juin 2007, 18:19

Non, non et non. Le code que tu présentes pour te prémunir des balises HTML est totalement inutile.

Pourquoi ?

La fonction strip_tags() supprime les balises HTML. Dès lors les fonctions htmlspecialchars() et htmlentities() ne servent à rien derrière. Tu n'as besoin que d'une fonction. Si tu veux supprimer totalement les balises HTML tu gardes juste strip_tags(). Si tu veux que les balises soient affichées mais qu'elles n'aient pas une signification en HTML, tu utilises htmlspecialchars(). Quand à htmlentities(), c'est la même chose que htmlspecialchars() mais en un peu plus complet, mais htmlspecialchars() convient très bien. De plus le flag ENT_QUOTES n'a à mon avis que peu d'utilité quand il s'agit juste de se prémunir des codes HTML utilisateurs.

Même chose pour la protection avant insertion SQL, pas besoin de faire plusieurs fois la même chose. Je te conseille de ne garder que la fonction d'échappement propre à ta base de données (mysql_real_escape_string() dans ton cas).
Klomac - Blog Lambda

Eléphant du PHP | 259 Messages

02 juin 2007, 18:27

d'accord merci
l'hébergeur gratuit que j'utilisais: http://www.freeheberg.com (pas de limitte de débit, BP, 1à10Go, bdd mysql illimitées )
mainteant je suis chez OVH, payant mais plus adapté à de gros sites

Eléphant du PHP | 63 Messages

05 juin 2007, 03:06

La solution d'@rthur me semble la plus efficace. Pour ton problème, il faut la combiner avec des expressions régulières :
$tab_pages_autorisees=array("`accueil\.php`", "topic\.php\?id=[0-9]+`");
$page_demandee=$_GET['page'];

$page = 'index.php' ;
foreach($tab_pages_autorisees as $page_autorisee)
     if (preg_match($page_autorisee, $page_demandee))
          $page = $page_demandee ;
Si tu es véritablement soucieux de la sécurité, n'oublie pas qu'il est toujours plus difficile d'exclure toutes les valeurs indésirables que d'autoriser uniquement les valeurs attendues.