2009-10-18 4 views
4

J'ai une application PHP qui utilise un paramètre $_GET pour sélectionner les fichiers JS/CSS sur le système de fichiers.Est-ce que ASCII "../" est la seule séquence d'octets qui indique une traversée de répertoire en PHP?

Si je nie toutes les demandes dans lesquelles la chaîne d'entrée contient ./, \ ou un octet en dehors de la plage ASCII 7 bits visible, est-ce suffisant pour empêcher traversals répertoire parent lorsque le chemin est passé à PHP sous-jacent (C-basé) les fonctions de fichier?

Je connais null-byte vulnerabilities, mais y a-t-il d'autres astuces de codage de caractères alternatives/malformées qui pourraient grincer par ces vérifications?

est ici l'idée de base (pas de code de production):

$f = $_GET['f']; // e.g. "path/to/file.js" 

// goal: select only unhidden CSS/JS files within DOC_ROOT 
if (! preg_match('@^[\x20-\x7E][email protected]', $f)  // outside visible ASCII 
    || false !== strpos($f, "./")    // has ./ 
    || false !== strpos($f, "\\")    // has \ 
    || 0 === strpos(basename($f), ".")  // .isHiddenFile 
    || ! preg_match('@\\.(css|js)[email protected]', $f) // not JS/CSS 
    || ! is_file($_SERVER['DOCUMENT_ROOT'] . '/' . $f)) { 
    die(); 
} 
$content = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/' . $f); 

Mise à jour: Ma question est vraiment sur la façon dont les fonctions du système de fichiers C interprètent des séquences ASCII arbitraires (par exemple, s'il y a des séquences d'échappement sans-papiers), mais Je me rends compte que cela est probablement lié au système et peut-être sans réponse dans la pratique.

Ma validation active nécessite en outre que realpath($fullPath) départ avec realpath($_SERVER['DOCUMENT_ROOT']), assurant que le fichier est dans le doc_root, mais un but de cette annonce était de fossé realpath() (il est prouvé peu fiable dans divers environnements) tout en permettant d'inhabituel, mais URIs valides comme /~user/[my files]/file.plugin.js.

+2

Cela ressemble à l'énumération de la méchanceté. Pouvez-vous prendre plus d'une approche de liste blanche en créant une liste de caractères juridiques à la place? – recursive

+0

D'accord; C'est une idée terrible de quelque façon que ce soit. –

+0

Par exemple, ma réponse. – SLaks

Répondre

1

Vous le mentionnez vous-même, mais comparer realpath de l'entrée à une racine connue est la meilleure solution que je peux penser. Realpath résoudra toutes les fonctionnalités cachées du chemin/système de fichiers, y compris les liens symboliques.

+0

Ouais, je pense que je vais devoir vivre avec les particularités de 'realpath'. –

5

Lorsque vous filtrez l'entrée pour des raisons de sécurité, utilisez toujours des listes blanches et non des listes de diffusion.

Vous devez rejeter tous les chemins qui ne correspondent pas /^([A-Za-z0-9_-]+\/?)*[A-Za-z0-9_-]+\.(js)|(css)?$/.

Cela autorisera uniquement les chemins segmentés normaux dans lesquels chaque segment comporte des lettres, des chiffres ou _-.

+0

Pourquoi cela a-t-il été déprécié? – SLaks

1

pourrions avoir besoin d'un peu rearchitecting, mais même si vous êtes passé ../../passwd, basename() va l'isoler. Ensuite, vous pouvez placer tous les fichiers que vous voulez servir dans un dossier.

Étant donné ../../././././a/b/c/d.txt, basename($f) sera d.txt; cette approche me semble plus judicieuse, au lieu d'essayer de déjouer l'utilisateur et d'oublier un trou.

+0

Il veut des sous-répertoires de serveur. – SLaks

+0

@SLaks: d'où: "Pourrait nécessiter un peu de réarchitecture" –

Questions connexes