2010-09-12 79 views
0

我有一個PHP腳本,測試用戶是否登錄,他訪問的每個頁面都在某個子目錄中。如果他已經登錄,他會得到該頁面,否則他會被重定向到登錄頁面。相反,包括到每一個文件(不可能的,因爲有些是二進制)這一點,我設置的.htaccess這樣PHP身份驗證+ mod_rewrite

RewriteEngine On 

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

而且check.php的內容

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

的問題是,檢查.php易受本地文件包含,因爲我可以通過../在文件名中移動到父目錄,甚至離開/ var/www。我如何限制它只能從特殊目錄中讀取,或者如果PHP檢查通過允許Apache讀取目標文件而不是讀取文件的PHP腳本,我可以通過什麼方式取消重寫?

編輯我也有特殊目錄中的子目錄。 check.php位於特殊目錄的父目錄中。

+0

這不適用於二進制。需要正確的頭文件 – 2010-09-12 11:58:35

+0

是的,它是check.php的簡化模型。我也可以找到文件的MIME類型並在頭文件中發送Content-Type。 – Dmi 2010-09-12 12:12:44

回答

0

這工作:

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

如果到文件名的真正路徑不以該字符串開始,它將中止。

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

將只留下文件名關閉任何給定的字符串

+0

對不起,我忘了補充一點,我在目錄中也有子目錄,所以我不能刪除整個路徑。 – Dmi 2010-09-12 12:14:32

0

首先,從你的mod_rewrite規則刪除「/特殊」的一部分,沒有必要爲它,你只想要一個文件名。

那就試試這個:

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

基名()將切斷從$文件名的路徑。

0

爲dir樹設置自動前綴不是簡單嗎?

+0

如果我預先添加「subdir /」並且有人輸入「../file」,他們會得到「/ file」而不是「subdir/file」。函數realpath解決了所有這些問題,以準確顯示它將要使用的路徑,並且如果它不以「subdir /」開頭,我知道它不在目錄中。 – Dmi 2010-09-15 22:57:34