2014-12-23 6 views
4

У меня есть php-файл с именем gallery.php, который является страницей для конкретной галереи изображений. Для безопасности пользовательские изображения хранятся вне корневого каталога.PHP - Безопасность при доступе к файлам за пределами веб-корня

Чтобы получить соответствующие файлы для каждого пользователя, я использую файл getimage.php, который служит изображениям из их местоположения. В целом, структура каталогов выглядит следующим образом:

  • UserImages
    • пользователь user1
      • Список изображений пользователя 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, хотя я уверен, что могут быть другие возможности атаки, которые я не содержал с этим скриптом.

По этой причине я бы предпочел, чтобы я мог перемещать getimage.php за пределы webroot или, по крайней мере, препятствовать тому, чтобы он был доступен напрямую (и только через gallery.php, где переданный параметр img строго под моим контролем).

Каждый раз, когда я пытаюсь переместить getimage.php oustide из public_html, я не могу больше назвать его, даже если я требую или включаю в gallery.php. Способ получить доступ к getimage.php делает это:

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

Но getimage.php потерпит неудачу, если я когда-либо переместить его из директории public_html.

Итак, длинный рассказ: что мне нужно сделать, чтобы предотвратить заражение getimage.php?

+0

Поскольку изображения должны быть поданы в Интернете, я не думаю, что их хранение за пределами веб-корня - хорошая идея, так как для их обслуживания вам все равно нужно создать дыру в безопасности. Вместо этого я бы подтвердил, что загруженные файлы - это действительно изображения, а затем сделать их доступными для Интернета. http://stackoverflow.com/questions/6755192/uploaded-file-type-check-by-php –

+0

Мне не нужна проверка загрузки, так как файлы, которые будут поданы, все мои собственные. Пользователь просто должен уметь их видеть. Если бы я разместил пользовательские изображения внутри веб-корневого компьютера, как мне предотвратить доступ к файлам User1 от пользователя 1? – BurnerBoy

+0

Я смущен тем, почему вам нужно будет закрепить некоторые изображения. Для меня, кажется, проблема здесь. Почему бы не переместить ваши изображения в субдомен (полностью отдельно от вашего приложения) и обслуживать их оттуда? – Piry

ответ

1

Для доступа к этой папке с изображениями с помощью директивы Directory (http://httpd.apache.org/docs/2.2/mod/core.html#directory) необходимо разрешить Apache (предполагается).

Или вы можете перемещать изображения в корневом каталоге и ограничивать прямой доступ к ним с помощью .htaccess, если вы хотите сохранить их защищенными.

+0

Я хотел использовать такое решение в сочетании с страницей входа, но я не знал, как это сделать. Есть ли способ использовать .htaccess в сочетании с страницей входа, а не всплывающим окном на основе браузера? – BurnerBoy

+0

Конечно, вы можете. Вы можете использовать rewrite (http://httpd.apache.org/docs/2.4/rewrite/flags.html) для пересылки всех запросов (за исключением css, ico и js) на свою страницу, где вы можете иметь логин и скрипт для предоставления изображений с чем-то вроде: «RewriteRule! \. (js | ico | css) $ index.php» в вашем .htaccess – Dukecz

1

Единственный способ сделать это с использованием структуры каталогов - очистить переменную $ _GET ['img'] и убедиться, что у нее нет никаких нежелательных символов.

Вы можете сделать это с помощью регулярного выражения, которое фильтрует все, кроме букв, цифр, символов подчеркивания, дефис и точек.

Попробуйте заменить первую строку кода с этим ...

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

В качестве альтернативы вы можете проверить, если $ _GET [ «IMG»] переменная содержит недопустимые символы с этой простой Если заявление перед вашим код.

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

PS: не забудьте проверить свой файл перед его чтением или вы получите ошибки, если это не так. Вы можете использовать существование файлов в качестве дополнительной проверки безопасности.

1

Лучший безопасный способ - не передавать URL изображения с использованием $ _GET ['img'], но вместо этого отправьте ссылку на изображение.

Проблема

Во-первых, $ _GET [ 'IMG'] может быть любой внешний URL для вредоносного кода, и с file_get_contents вы загружаете его непосредственно.

Во-вторых, любой человек может использовать сервер в качестве бесплатного прокси изображения, просто используя следующий URL в своем собственном веб-сайте:

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

правильный путь

1) В базе данных создать таблицу изображений содержащие пути к изображениям пользователей. Если вы хотите, чтобы служить изображение передать изображение ID вместо URL:

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

2) Потому что вы знаете, что $ _GET [ «изображение»] является идентификатором можно дезинфицировать легко:

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

3) в вашем SQL не забудьте использовать подготовленное statments:

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

4) только изображения должны быть перемещены за пределами корневой папки документов, если вы хотите переместить getimage.php внешнего корня, а вы можете использовать Apache Алиас служить ему. В Apache VirtualHost конфигурации вы можете использовать:

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

5) Использование не найден 404 вместо 403 запретного, не дают злоумышленнику подсказку, что вы поймали его действия.