2010-09-12 4 views
0

J'ai un script PHP qui vérifie que l'utilisateur est connecté, pour chaque page qu'il accède dans un certain sous-répertoire. S'il est connecté, il obtient la page, sinon il est redirigé vers une page de connexion. Au lieu d'inclure cela dans tous les fichiers (pas possible car certains sont binaires), je .htaccess mis en place comme celui-ciAuthentification PHP + mod_rewrite

RewriteEngine On 

RewriteCond %{REQUEST_FILENAME} !^$ 
RewriteRule (.*) /check.php?filename=special/$1 

Et le contenu de check.php sont

if (!isset($_SESSION['username'])) 
{ 
    header("location: /login.html"); 
    die(); 
} 
$filename = $_GET['filename']; 
include($filename); 

Le problème est que l'enregistrement .php est vulnérable à l'inclusion de fichier local parce que je peux passer ../ dans le nom de fichier pour aller dans le répertoire parent et même quitter/var/www. Comment puis-je le restreindre à la seule lecture depuis le répertoire spécial, ou y a-t-il un moyen de le réécrire si la vérification PHP passe pour permettre à Apache de lire le fichier cible au lieu du script PHP lisant le fichier?

Modifier J'ai également des sous-répertoires dans le répertoire spécial. check.php se trouve dans le répertoire parent du répertoire spécial.

+0

cela ne fonctionnera pas avec binaire. l'en-tête approprié est requis –

+0

Oui, c'est un modèle simplifié de check.php. Je trouve aussi le type mime du fichier et envoie Content-Type dans l'en-tête. – Dmi

Répondre

0

Cela a fonctionné:

$filename = realpath($_GET['filename']); 
if (strpos($filename, '/full/path/to/special') !== 0) 
{ 
die(); 
} 

Si le chemin réel au nom de fichier ne commence pas par cette chaîne, il avorte.

0
$filename = basename($_GET['filename']); 

ne laissera que de nom de fichier une chaîne donnée

+0

Désolé, j'ai oublié d'ajouter que j'ai aussi des sous-répertoires dans le répertoire, donc je ne peux pas supprimer tout le chemin. – Dmi

0

Tout d'abord, laissez tomber la partie «/spéciale » de votre règle de mod_rewrite, il n'y a pas besoin, vous voulez juste un nom de fichier.

Ensuite, essayez ceci:

$your_dir = '/full/path/to/special'; 
$filename = basename($_GET['filename']); 
if (file_exists($your_dir . '/' . $filename)) { 
    include($filename); 
} 

basename() coupera tout chemin de nom de fichier $.

0

Ne serait-il pas plus simple de définir un auto-préfixe pour l'arborescence de dir?

+0

Si je préfixe "subdir /" et que quelqu'un entre "../fichier", ils obtiennent "/ fichier" au lieu de "sous-répertoire/fichier". La fonction realpath résout tout cela pour montrer exactement quel chemin elle va, et si elle ne démarre pas avec "subdir /", je sais que c'est hors du répertoire. – Dmi