2012-03-18 5 views
1

J'ai un code comme ceci:

$myvar=$_GET['var']; 

// a bunch of code without any connection to DB where $myvar is used like this: 

$local_directory=dirname(__FILE__).'/images/'.$myvar; 
if ($myvar && $handle = opendir($local_directory)) { 
    $i=0; 
    while (false !== ($entry = readdir($handle))) { 
     if(strstr($entry, 'sample_'.$language.'-'.$type)) { 
      $result[$i]=$entry; 
      $i++; 
     } 
    } 
    closedir($handle); 
} else { 
    echo 'error'; 
} 

Je suis un peu confus avec un certain nombre de décapage et échapper à des fonctions, la question est, qu'est-ce que je dois faire avec $myvar pour que ce code soit sûr? Dans mon cas, je ne fais aucune connexion à la base de données.

+0

Le répertoire '. $ Myvar' existe-t-il déjà ou le créez-vous à la volée? –

+0

@Pekka: Ce code ne crée rien à la volée. –

+0

Est-ce que désinfecter toutes les entrées avec des filtres php, il devrait être plus que suffisant pour votre code. http://br.php.net/manual/fr/filter.filters.sanitize.php – B4NZ41

Répondre

5

Vous essayez d'empêcher les attaques de traversée de répertoire, vous ne voulez donc pas que la personne mette ./../../../ ou quelque chose, espérant lire des fichiers ou des noms de fichiers, selon ce que vous faites.

Je souvent en utilisant quelque chose comme ceci:

$myvar = preg_replace("/[^a-zA-Z0-9-]/","",$_GET['var']); 

Cela remplace tout ce qui est pas a-zA-Z0-9- avec un blanc, donc si la variable contient dire *, ce code supprimerais que. Puis, je change le a-zA-Z0-9- pour correspondre aux caractères que je veux autoriser dans la chaîne. Je peux ensuite le verrouiller pour ne contenir que des chiffres ou tout ce dont j'ai besoin.

+0

fonctionne bien dans la plupart des cas. attention doit être payé lorsque vous avez des données que vous souhaitez protéger dans un dossier frère. C'est pourquoi j'ai tendance à préférer explicitement ce qui est permis, plutôt que d'essayer de bloquer ce que j'éviterais. – maraspin

+2

Oui, bien sûr. Dans les cas où c'est très clair, vous pouvez changer la regex à quelque chose comme "/^(option1 | option2 | option3)"/à la place. Toujours restreindre l'entrée autant que possible. –

+0

Toutes les bonnes suggestions en effet. J'ai tendance à m'appuyer sur des tableaux (ou d'autres choses dans des situations plus complexes) en raison de la flexibilité de synchroniser w/FS et d'éviter la duplication de code/logique. Mais bon, bons points de toute façon. – maraspin

3

Il est vraiment, vraiment dangereux de faire quelque chose comme: opendir($local_directory)$local_directory est une valeur qui pourrait provenir de l'extérieur. Et si quelqu'un passe quelque chose comme ../../../../../../../../../etc ... ou quelque chose comme ça? Vous risquez de compromettre la sécurité de votre hôte.

Vous pouvez prendre un coup d'oeil ici, pour commencer: http://php.net/manual/en/book.filter.php

à mon humble avis, si vous ne créez rien à la volée, vous devriez avoir quelque chose comme:

$allowed_dirs = array('dir1','dir2', 'dir3'); 
if (!in_array($myvar, $allowed_dirs)) { 
    // throw an error and log what has happened 
} 

Vous pouvez le faire juste après avoir reçu votre contribution de "dehors". S'il vous est impossible de le faire car le nombre de répertoires d'images peut varier avec le temps et que vous avez peur de manquer la synchronisation avec votre base de code, vous pouvez également remplir le tableau de valeurs valides en scannant les sous-répertoires dossiers en premier.

Ainsi, à la fin, vous pourriez avoir quelque chose comme:

$allowed_dirs = array(); 
if ($handle = opendir(dirname(__FILE__) . '/images')) { 
    while (false !== ($entry = readdir($handle))) { 
      $allowed_dirs[] = $entry; 
    } 
    closedir($handle); 
} 
$myvar=$_GET['var']; 

// you can deny access to dirs you want to protect like this 
unset($allowed_dirs['private_stuff']); 

// rest of code 
$local_directory = dirname(__FILE__) . "/images/.$myvar"; 
if (in_array(".$myvar", $allowed_dirs) && $handle = opendir($local_directory)) { 
    $i=0; 
    while (false !== ($entry = readdir($handle))) { 
     if(strstr($entry, 'sample_'.$language.'-'.$type)) { 
      $result[$i]=$entry; 
      $i++; 
     } 
    } 
    closedir($handle); 
} else { 
    echo 'error'; 
} 

code est pas optimisé ci-dessus. Mais évitons dans ce cas une optimisation prématurée (en indiquant ceci pour éviter une autre "baisse"); L'extrait est juste pour vous donner l'idée d'autoriser explicitement les valeurs VS l'approche alternative de tout autoriser à moins de correspondre à un certain modèle. Je pense que le premier est plus sûr.

+1

N'importe quel exemple comment le filtrer? – Gumbo

+0

tnx pour le downvote. Mon approche ne semble pas si mauvaise .. – maraspin

+0

La bonne chose à propos de la coloration syntaxique est que certaines erreurs sont immédiatement visibles. –

1

Comme pour toutes les données provenant d'une source non fiable: Validez-la avant utilisation et codez-la correctement lorsque vous la transmettez à un autre contexte. Comme pour le premier, vous devez d'abord spécifier quelles propriétés les données doivent avoir pour être considérées comme valides. Cela dépend principalement de l'objectif de son utilisation.

Dans votre cas, la valeur de $myvar doit probablement être au moins un nom de répertoire valide mais il peut également s'agir d'un chemin relatif valide composé de noms de répertoire, en fonction de vos besoins. À ce stade, vous êtes censé spécifier ces exigences.

2

Permettez-moi de souligner que pour être complet que, si vous pouvez être sûr que votre code ne sera exécuté sur les systèmes de type Unix (comme Linux), les que choses que vous devez vous assurer sont que:

  1. $myvar ne contient aucune barre oblique ("/", U + 002F) ou nulle ("\0", U + 0000) caractères, et que

  2. $myvar est non vide ou égale à "." (ou, de manière équivalente, que ".$myvar" n'est pas égal à "." ou "..").

C'est parce que, sur un système de fichiers Unix, le seul caractère séparateur de répertoire (et l'un des deux caractères non autorisés dans les noms de fichiers, l'autre étant le caractère nul "\0") est la barre oblique, et les seules entrées de répertoire spéciales pointant vers le haut dans l'arborescence sont "." et "..". Toutefois, si votre code peut un jour être exécuté sous Windows, vous devrez désactiver davantage de caractères (au moins la barre oblique inverse, "\\", et probablement d'autres également). Je ne connais pas assez avec les conventions du système de fichiers Windows pour dire exactement quels caractères que vous auriez besoin de désavouer là, mais l'approche sécuritaire est de faire as Rich Bradshaw suggests et ne permettent aux personnages que vous connaissez sont en sécurité.

Questions connexes