簡體   English   中英

PHP - 訪問Web根目錄之外的文件的安全性

[英]PHP - Security in accessing files outside of web root

我有一個名為gallery.php的php文件,它是用戶特定圖像庫的頁面。 為了安全起見,用戶圖像存儲在Web根目錄之外。

要為每個用戶檢索適當的文件,我使用getimage.php文件,該文件從其位置提供圖像。 總而言之,目錄結構如下所示:

  • UserImages
    • 用戶1
      • user1的圖像列表
    • 用戶2
      • user2的圖像列表
  • 的public_html
    • gallery.php
    • getimage.php

getimage.php編寫如下:

$imgString = realpath('/UserImages/' . $_SESSION['username'] . '/' . $_GET['img']);
if (!startsWith($imgString, '/UserImages/' . $_SESSION['username'] . '/')
    || !(endsWith(strtolower($imgString), '.jpg') || endsWith(strtolower($imgString), '.jpeg')))
{
    header('HTTP/1.0 403 Forbidden');
    die();
}

$img = file_get_contents($imgString);
header("Content-type: image/jpeg");
echo($img);
exit();

我依靠$ _GET ['img']來確定要檢索的圖像,這是一個可能的安全漏洞(也是一個主要漏洞)。 我可以預見目錄遍歷攻擊,因此使用realpath,雖然我確信可以有其他攻擊途徑,我不包含此腳本。

出於這個原因,我更喜歡我可以在webroot之外移動getimage.php,或者至少阻止它直接訪問(並且只能通過gallery.php,其中發送的img參數嚴格在我的控制之下)。

每當我嘗試移動public_html的getimage.php oustide時,即使我在gallery.php中執行require或include,我似乎也無法再調用它。 我訪問getimage.php的方式是這樣做的:

<img src=getimage.php?img=IMG_FILENAME.jpg />

但如果我將它移出public_html目錄,getimage.php將失敗。

所以,長話短說:我需要做些什么才能防止getimage.php被濫用?

最安全的方法是不使用$ _GET ['img']傳遞圖片網址,而是發送對圖片的引用。

問題

首先,$ _GET ['img']可以是有害代碼的任何外部URL,而使用file_get_contents,您可以直接下載它。

其次,任何人都可以通過在自己的網站中使用以下網址將您的服務器用作免費圖像代理:

<img src="http://www.yourwebsite.com/getimage.php?img=[external_image_url]">

正確的方式

1)在數據庫中創建包含用戶圖像路徑的圖像表。 當您想要提供圖像時,請傳遞圖像ID而不是網址:

$imageID = $_GET['image'];
.... your sql query here to retrieve the image....
$img = file_get_contents($imgString);

2)因為您知道$ _GET ['image']是一個ID,您可以輕松地清理它:

if( !preg_match("/^[0-9]+$/", $_GET['image']) )
{
    header('HTTP/1.1 404 Not Found');
    exit();    
}

3)在你的SQL中別忘了使用准備好的語句:

$sql = "SELECT image_path from images WHERE id = ?";

4)只有圖像應該移動到文檔根文件夾之外,如果你想在根目錄外移動getimage.php,你可以使用Apache Alias來提供它。 在Apache Virtualhost配置中,您可以使用:

Alias /getimage.php /path/to/getimage.php

5)使用404 not found而不是403禁止,不要給攻擊者一個提示你抓住了他的動作。

您需要允許Apache(假設)使用Directory指令( http://httpd.apache.org/docs/2.2/mod/core.html#directory )訪問帶有圖像的文件夾。

或者,您可以在根目錄下移動圖像,並使用.htaccess限制對它們的直接訪問,如果您想保護它們。

使用目錄結構執行此操作的唯一方法是清除$ _GET ['img']變量並確保它沒有任何不需要的字符。

您可以使用正則表達式來執行此操作,該表達式可以過濾除字母,數字,下划線,連字符和點之外的所有內容。

嘗試用這個代替代碼的第一行......

$imgString = realpath('/UserImages/' . $_SESSION['username'] . '/' . preg_replace("/[^a-zA-Z0-9._-]/", "", $_GET['img']));

或者,您可以在代碼之前檢查$ _GET ['img']變量是否包含帶有此簡單If語句的錯誤字符。

if(preg_replace("/[^a-zA-Z0-9._-]/", "", $_GET['img']) != $_GET['img']){
    // Throw an error
    exit();
}

PS:在閱讀之前不要忘記檢查文件是否存在,否則會出現錯誤。 您可以將文件存在作為附加安全檢查。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM