2013-04-17 36 views
0

包含從查詢字符串獲取文件夾和文件名的文件的最佳方式是什麼?php包含來自查詢字符串的可變文件

myServer.com/data有數百個文件夾中有幾個文件。 這些是純html文件。

myServer.com/code是一個PHP targetPage.php

我可以建立一個這樣的URL:

http://www.myServer.com/code/targetPage.php?folder=folder132&name=file23 

什麼是閱讀中的源文件的PHP源文件夾,並將源「div」的內容作爲targetDiv的innerHTML包含在目標頁面中?

<body><div id="targetDiv">This is the place holde div</div> 

我對PHP比較陌生,因此是個問題。

+2

請不要這樣做。這個腳本產生很大的安全問題。 –

+1

「文件夾」參數始終是單個名稱還是可以具有目錄分隔符? –

+1

攻擊者可以將php腳本添加到任何文件類型而不更改MIME類型和擴展名。他可以執行該操作。請檢查此鏈接http://security.stackexchange.com/questions/32967/is-it-possible-to-execute-a-php-script-in-an-image-file –

回答

1

首先,讓絕對確定包含的文件是允許的,最好是使用whitelist

然後,您可以使用像file_get_contents()這樣的函數將文件讀取到字符串中並使用echo輸出。

爲了結束(這是一個辦法做到這一點,還存在其他途徑):

$file = $_GET['folder']."/".$_GET['file']; 

if (in_array($file, $whitelist)) { 
    $contents = file_get_contents($file); 
} else { 
    $contents = "Not allowed"; 
} 

echo "<body><div id='targetDiv'>$contents</div>" 

例如,您可以通過掃描你希望能夠以顯示目錄生成的白名單。 (這不在這個答案的範圍之內;-))。

另一種解決方案可能是使用realpath()檢查規範結果路徑。

+0

我並不是說不可能使這項工作具有一定的安全性,但我敢打賭,有一些方法可以在已經構建的結構中完成同樣的事情,通過在請求映射到期望的文件,然後完全不公開給訪問者的PHP代碼會將其轉換爲適當的文件引用。 – Craig

+0

@Craig - Exactement,mon ami :-) –

+0

@Craig我同意,但海報聲明他有幾百個文件夾,可能由一些其他程序生成。生成ID意味着有另一個任務,更多的代碼,因此更多的錯誤。我建議的基本上是使用文件夾和文件名作爲它們的ID並將它們映射到文件。 –

1

這基本上是對潛在黑客的邀請,他們毫無疑問會感謝您讓他們能夠輕鬆指定哪些文件包含在PHP頁面中(並因此執行)。

乍一看,這至少與導致SQL注入攻擊的問題類似。你真的確定你想從查詢字符串中獲取包含文件的路徑嗎?查詢字符串暴露給最終用戶。我看到的一個問題是,這往往會將訪問者的網站內部結構暴露出來。另一個問題是,作爲訪問者,我可以試驗不同的包含文件,直到我大概發現某個以某種方式(最好)或(最壞的情況下)破壞網站的人破壞您的安全並給予我更大的訪問權限到你的服務器或你的數據庫,這會讓我更深入地瞭解你的系統,直到我完全受損,或者能夠刪除或更新你不想讓我的數據庫中的東西。通過「我」和「我」,當然我假設有人試圖破解你的網站。

我會探索找到一個不同的(服務器端,不暴露給訪客)的方式來找出哪個文件包含。

+1

如何在沒有SQL的情況下進行SQL注入? –

+0

那麼,在這種情況下,它會是PHP注入,是嗎?不過,相同的基本概念。 :-) – Craig

+0

我認爲沒有危險,因爲查詢字符串不會是明確的:它將包含類似於「?paramA = 123?paramB = 12」的東西,而不是顯式路徑。使用「123」,我將設置文件夾路徑並使用paramB文件名。 –

0

如果該文件夾應該只是一個沒有目錄分隔符的名稱,則可以使用basename()從文件夾和名稱中去除分隔符。該文件夾需要特殊處理,因爲..在技術上是有效的,但您不希望允許超出您的基本目錄。

if (isset($_GET['folder'], $_GET['name'])) { 
    $folder = trim(basename($_GET['folder']), '.') ?: '.'; 
    $name = basename($_GET['name']); 

    $file = BASE_DIR . "/$folder/$name"; 
    if (is_file($file) && is_readable($file)) { 
     echo file_get_contents($file); 
    } 
} 

BASE_DIR將包含從中加載文件的基本目錄的常數。

+0

PHP中有一個'realpath'函數,它給你實際的路徑,沒有點和所有的。 –

+0

@BartFriederichs是的,但是很好地給出'../../../../ etc/passwd'的絕對路徑:)即不安全。 –

+0

不,'realpath('../../../../ etc/passwd')'是'「/ etc/passwd」'。 –