Page 1 sur 1

probleme pour securiser les includes : marche pas !

Posté : 21 févr. 2007, 11:55
par telecofr
Salut, :)
j'ai utilisé une méthode classique pour sécuriser mes includes, mais cela ne marche pas... :(

Voici mon bout de code :
<?php $page = (!empty($_GET['page'])) ? htmlentities($_GET['page']) : 'index';
// On définit le tableau contenant les pages autorisées
$pageOK = array('index' => 'index.php',
                'page1' => 'page1.php',
                'page2' => 'page2.php',
                'erreur' => 'erreur.php');
// On teste que le paramètre d'url existe et qu'il est bien autorisé
if(!array_key_exists($page, $pageOK)) // s'il n'y a pas le nom de la page dans la tableau => affiche l'accueil du site
        include('index.php');
elseif(!is_file($pageOK[$page])) // si le nom de la page existe dans le tableau mais que le fichier correspondant a été effacé => message 404 d'erreur
        include('erreur.php');
else // sinon on affiche la page demandée
        include($pageOK[$page]);
?>
Pour les pages déclarées dans le tableau, cela fonctionne bien, mais quand je fais un test avec une page qui n'est pas dans le tableau (toto par exemple :) ), ou une page qui est dans le tableau (page2 par exemple) mais dont le fichier page2.php a été effacé, j'obtiens toujours le message suivant :
Champ 'toto' inconnu dans field list
ou
Champ 'page2' inconnu dans field list
Je ne vois pas ce qui cloche ! :?

Merci de votre aide !

Posté : 21 févr. 2007, 18:49
par AB
Bonjour,

Chez moi ton code fonctionne. Cela dit tu pourrais faire plus simple avec les mêmes fonctionalités :
<?php $page = (!empty($_GET['page'])) ? htmlentities($_GET['page']) : 'index';

// On défini la page à inclure suivant la valeur de $page
switch ($page) {
	case "index" : $page = "index.php"; break;
	case "page1" : $page = "page1.php"; break;
	case "page2" : $page = "page2.php"; break;
	case "erreur" : $page = "erreur.php"; break;
	default : $page = "index.php"; 
	}
	
$page = file_exists($page)? $page : 'erreur.php';

?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Document sans titre</title>
</head>

<body>
<div>
<?php include($page); ?>
</div>
</body>
</html>

Posté : 22 févr. 2007, 00:55
par Ryle
A ce compte là...
<?php
$page = (isSet($_GET['page']) && !empty($_GET['page'])) ? htmlentities($_GET['page']) : 'index'; 
     
if (!file_exists($page.'.php')) 
  $page = 'erreur';

include ($page.'.php');
?>
;)

Posté : 22 févr. 2007, 04:33
par AB
Bonjour,

C'est pas un peu téméraire, Ryle ? aucun doute qu'on ne puisse jamais détourner file_exists() :?:

Posté : 22 févr. 2007, 09:36
par Ryle
Euh... ouais... c'était un peu barbare je reconnais, mais il était tard aussi ;)

Et effectivement, si tu passe l'url d'un script php sans l'extension, il sera sauvagement inclu... mais pour éviter cela, il suffit de spécifier que l'on part du dossier en cours pour l'include en préfixant le chemin de "./"

L'avantage (pour un paresseux comme moi ;)) c'est que tu n'a plus alors de table de correspondance à maintenir à chaque fois que tu ajoutes une nouvelle page ou que tu changes le nom, c'est pris en compte automatiquement.

A partir de la, si c'est pas sur ton serveur ça peut plus être ouvert. Par contre et pour sécuriser d'avantage il faudrait également contrôler que la variable ne contient pas la chaine "../"
Certains bloquent juste "/" tout simplement, mais personnellement je l'utilise, ca me permet de structurer mes fichiers en arbo et d'inclure la page "dossier/sous-dossier/page" sans problème (en ajoutant le "./" ... ".php") :)

Posté : 22 févr. 2007, 09:44
par Jules Petibidon
hello,

Personellement je préfere le systeme de white list de telecofr.
pourquoi ?

1) @AB : le systeme de switch est certes bien, mais si tu rajoute un module, tu dois reprendre ton script principal pour rajouter un "case" : c'est chiant. une white list peut etre importée depuis une base de données ou un fichier sans probleme et permet une grande souplesse.

2) @Ryle : l'include direct d'une page si elle existe peut permettre par exemple de faire quelque chose telle que ceci : monsite.com/index_public.php?page=admin/delete&quoi=un_truc_qu_y_faut_pas.
certes le risque est normalement tres faible, cela implique que le module "delete" n'est pas sécurisé (ce qui est souvent le cas puisqu'on imagine qu'il est normalement appelable que depuis une page authentifée et sécurisée, elle), que la personne qui fait cela connait la structure du systeme, et qu'elle est vraiment malveillante... mais est ce un scénario impossible ?

3) @telecofr :
3a: quel est l'interet d'un htmlentities sur $page avant de tester ?
3b: array_key_exists... c'est pas plus simple de faire un isset( $pageOK[ $_GET['page'] ] ) ?
3c: si la page est dans la white list, il n'est pas nécessaire de faire un file_exists ensuite... logiquement...

bonne nourjée !

Posté : 22 févr. 2007, 15:05
par telecofr
merci de votre aide ! :wink:

j'ai donc modifié quelques trucs de mon code. Voila ce que j'ai dans mon fichier index.php :
<body>
<?php
$page = (!empty($_GET['feuil'])) ? $_GET['feuil'] : 'accueil';
// On définit le tableau contenant les pages autorisées
$pageOK = array('accueil' => 'accueil.php', 
			'livreor' => 'livreor.php',
			'contact' => 'contact.php');
// On teste que le paramètre d'url existe et qu'il est bien autorisé
if(isset($pageOK[$page]))
	include($pageOK[$page]);
else  
	include('accueil.php');
?>
</body>
Problème: cela ne marche toujours pas.

Ca m'affiche toujours un message style :
Champ 'XXX' inconnu dans field list
Je ne comprends pas d'où vient ce message d'erreur ! :shock:

Merci de votre aide !

Posté : 23 févr. 2007, 05:36
par AB
hello,

Personellement je préfere le systeme de white list de telecofr.
pourquoi ?

1) @AB : le systeme de switch est certes bien, mais si tu rajoute un module, tu dois reprendre ton script principal pour rajouter un "case" : c'est chiant. une white list peut etre importée depuis une base de données ou un fichier sans probleme et permet une grande souplesse.
Que la white list soit dans un swich ou dans un tableau, je ne vois pas bien ce que cela change, sauf cas particulier de l'enregistrement de cette liste dans un fichier.
Mais si c'est pour l'enregistrement dans une BDD qui procurera un maximum de souplesse, ce système est très adapté puisqu'il suffit de lister le switch avec les index et les pages correspondantes.
Par ailleurs cette syntaxe est plus optimisée et gagne en vitesse d'exécution tout en apportant les mêmes garanties.
Bon c'était pour chipoter un peu :wink:

Concernant tes réponses à télécofr
-3a : effectivement, j'y avais pensé mais j'avoue je me suis déjà laissé tenter par un surcroit de sécurité informatique (certainement dû au manque d'une bonne formation initiale - autodidacte). Mais dans ce cas au moins, si cela n'aide pas, cela ne devrait pas gêner.
-3c : télécofr, dans les commentaires de son code, veut pouvoir vérifier des pages inclues dans la white list mais qui pourraient avoir été effacées.

(Je suis légèrement pointilleux ces derniers temps car un peu insomniaque :))

@ Ryle, tu t'en tire bien...t'as de la change que les inspecteurs qui distribuent les macarons du guide michelin soient en vacance :lol:

@ télécofr

J'ai testé ton code en local (comme je l'indique plus haut) et il apparemment il fonctionne. Ton pb vient peut-être des pages que tu inclues ou de la page dans lequel ton code est inclus (variables communes ?)...Tu peux aussi essayer mon code pour savoir si ton bp vient du code lui-même ou d'autre part :wink:

Posté : 23 févr. 2007, 17:54
par telecofr
j'ai essayé ton code, AB, mais cela ne marche toujours pas quand je met un nom different... cela m'affiche toujours la meme erreur ! :(

Posté : 25 févr. 2007, 22:30
par AB
Bonsoir,

Ton message d'erreur ressemble à un message d'erreur de requête mysql. Ce n'est pas le code que tu nous a montré (ni le mien) qui est en cause mais certainement une erreur ailleurs dans ta page.

Posté : 25 févr. 2007, 23:41
par netsupra
Salut,
une petite regle d'inclusion que j'utilise depuis toujours sans problèmes, qui est je pense parfaitement sécurisée et qui evite l'emploi d'une white list :
if(isset($_GET['file']) and (!empty($_GET['file'] != '')))
     $page = './incl/' . $_GET['file'] . '.php'; 
else $page = './incl/home.php';  //Page d'accueil
if (!file_exists($page)) 
     $page = 'incl/erreur.php';  //Page en cas d'erreur
Pour l'utiliser, on créé un dossier "incl" a la racine du site.
Netsupra

Posté : 26 févr. 2007, 12:30
par telecofr
salut,

merci de votre aide !

Merci AB pour ta suggestion : après avoir buché ce weekend sur mon code, et en regardant de plus près les requêtes sql, je me suis aperçu que c'était bien un problème de requête ! :D

Explication :
En fait, dans l'organigramme de mes fichiers, j' "include" toujours au début de chaque fichier (accueil, livreor, contact) le fichier compteur.php
(tout au début de chaque fichier, il y a donc
<?php
include('compteur.php');
?>
)
Dans ce fichier compteur, j'incrémente de 1 la colonne correspondant à la page vue dans ma table visites.

Donc, quand je met index.php?page=nimportequoi, le fichier compteur va incrémenter la colonne "nimportequoi". Mais le problème est que cette colonne n'existe pas !!! D'où l'erreur !! :lol:

Maintenant, plus qu'à régler ce problème.

Pour cela, il faudrait que je change la valeur de page quand j'affiche la page d'accueil...
Mais je ne sais pas comment faire pour changer dans l'url la valeur de index.php?page=nimportequoi en index.php?page=accueil !

Si quelqu'un avait une idée !

Encore merci de votre aide ! :wink:

Posté : 26 févr. 2007, 22:33
par AB
Bonsoir,

Toujours avec le switch! (essaies d'utiliser cette fonction quand c'est possible car elle est très rapide à l'exécution tout en étant très lisible. C'est l'équivalent de plusieurs if sur la valeur d'une variable)

D'après ce que j'ai compris de ta dernière explication, plusieurs pages inclues peuvent composer ta page d'accueil. Tu dois certainement connaitre leur nom. Dans cet exemple si la valeur de $_GET['page'] va de nimportequoi1 jusqu'à nimportequoi4, $page_compteur = accueil

Pour que ta fonction compteur puisse se servir de la variable $page à incrémenter qui sera différente de la variable $page à inclure, tu peux faire comme ça: (si ton code n'est pas déjà défini, tu pourrais choisir des variables avec des noms différents)
<?php $page_compt = (!empty($_GET['page'])) ? $_GET['page'] : '';

switch ($page_compt) {
    case "nimportequoi1" : 
    case "nimportequoi2" :
    case "nimportequoi3" :
    case "nimportequoi4" : $page = 'accueil'; break;
    } 

include('compteur.php'); 

$page = (!empty($_GET['page'])) ? htmlentities($_GET['page']) : 'index';

// On défini la page à inclure suivant la valeur de $page
switch ($page) {
    case "index" : $page = "index.php"; break;
    case "page1" : $page = "page1.php"; break;
    case "page2" : $page = "page2.php"; break;
    case "erreur" : $page = "erreur.php"; break;
    default : $page = "index.php"; 
    }
    
$page = file_exists($page)? $page : 'erreur.php';

?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Document sans titre</title>
</head>

<body>
<div>
<?php include($page); ?>
</div>
</body>
</html>
[/php]

Posté : 27 févr. 2007, 10:00
par telecofr
ok, merci pour tout AB !! :)

je vais regarder cela de plus près.

a+