2016-05-11 21 views
0

это мой download.php;Force image download - .php files загрузить

session_start(); 
$file = $_GET['file']; 

    download_file($file); 
function download_file($fullPath){ 

    // Must be fresh start 
    if(headers_sent()) 
    die('Headers Sent'); 

    // Required for some browsers 
    if(ini_get('zlib.output_compression')) 
    ini_set('zlib.output_compression', 'Off'); 

    // File Exists? 
    if(file_exists($fullPath)){ 

    // Parse Info/Get Extension 
    $fsize = filesize($fullPath); 
    $path_parts = pathinfo($fullPath); 
    $ext = strtolower($path_parts["extension"]); 

    // Determine Content Type 
    switch ($ext) { 
     case "pdf": $ctype="application/pdf"; break; 
     case "exe": $ctype="application/octet-stream"; break; 
     case "zip": $ctype="application/zip"; break; 
     case "doc": $ctype="application/msword"; break; 
     case "xls": $ctype="application/vnd.ms-excel"; break; 
     case "ppt": $ctype="application/vnd.ms-powerpoint"; break; 
     case "gif": $ctype="image/gif"; break; 
     case "png": $ctype="image/png"; break; 
     case "jpeg": 
     case "jpg": $ctype="image/jpg"; break; 
     default: $ctype="application/force-download"; 
    } 

    header("Pragma: public"); // required 
    header("Expires: 0"); 
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 
    header("Cache-Control: private",false); // required for certain browsers 
    header("Content-Type: $ctype"); 
    header("Content-Disposition: attachment; filename=\"".$_REQUEST["isim"]."\";"); 
    header("Content-Transfer-Encoding: binary"); 
    header("Content-Length: ".$fsize); 
    ob_clean(); 
    flush(); 
    readfile($fullPath); 

    } else 
    die('File Not Found'); 

} 

Это принудительный файл загрузки jpg. Но этот файл может загружать все .php-файлы.

Normaly Я использую эту ссылку для скачивания и загружаю изображение; http://domain.net/download.php?file=wp-content/uploads/2016/04/10/126379-fantasy_art.jpg

Но тогда я проверил это ссылка скачать мой конфигурационный файл ... http://domain.net/download.php?file=wp-config.php

Я думаю, что это большая уязвима.

Как я могу это исправить? я не хочу загружать любые файлы .php ...

спасибо ..

+0

«Я думаю, что это большая уязвимость». Да ... да, очень. Хорошо, что ты поймал это. Самое простое решение - убедиться, что только файлы в определенном каталоге в порядке и соответствуют переменной '$ fullPath', перед тем как отправить что-нибудь обратно. –

ответ

1

Использовать по умолчанию в вашем случае переключения, чтобы избежать этой проблемы:

Удалить это:

default: $ctype="application/force-download"; 

Для этого: default: die('File not found'); или default: return false;

Также вы можете проверить, имеет ли смысл смысл, например, это должна быть подпапка uploads. У этого сообщения есть некоторая информация для вас: Test if a directory is a sub directory of another folder

+0

спасибо помощнику. и я добавляю «default: die (« Файл не найден »); теперь работает хорошо. благодаря тонну ! – Aytek

+0

убедитесь, что ваш $ ext правильный в этом случае. –

+0

спасибо помощнику. я заменяю «default: die (« Файл не найден »); этот код. теперь работаю хорошо ... – Aytek

0

Я думаю, было бы хорошо, если бы вы отступили и рассмотрите, что на самом деле делает этот сценарий, потому что он по-прежнему является гигантской дырой в безопасности. Вот что он делает:

  1. Возьмите вход пользователя (который всегда ненадежный)
  2. Смотрите, если это расширение допускается в соответствии с небольшой список возможных расширений
  3. Если да, то передать его в пользователь

Теперь, когда у вас есть возможность умереть за нераспознанные расширения файлов, он не позволит им загружать ваши фактические php-файлы. Но это все равно позволит пользователю делать всевозможные страшные вещи, все из которых сводятся к одному очень важному вопросу:

Вы не пытаетесь проверить, действительно ли запрашиваемый файл является разумным для просмотра человеком! !!

Ключевым моментом является то, что readfile() не заботится о том, где находится файл. Также не предполагается, что файл находится в общедоступном каталоге вашего веб-сайта. Единственная причина, по которой это загрузка файлов из вашего веб-каталога, заключается в том, что вы не запустили имя файла с косой чертой. Однако readfile() с радостью передаст что-либо на сервере, к которому он имеет доступ для чтения. Без вашего последнего изменения пользователь мог так же легко сделать это:

http://domain.net/download.php?file=/etc/passwd

Более того, он даже не должен быть фактический файл на сервере. В большинстве PHP-приложений PHP будет загружать URL-адреса в качестве реальных файлов.Так что кто-то может использовать скрипт в качестве прокси:

http://domain.net/download.php?file=http://theFBIwillArrestYouIfYouLoadThis.com/secrets.pdf

Такого рода уязвимости (способность использовать сценарий в качестве прокси-сервера), по-прежнему присутствует в вашем текущем решении. В любое время, когда я вижу, что веб-сайт принимает пути к файлам, как это, я хочу, чтобы узнать, насколько это позволит мне сойти с рук. Вы могли бы настроиться на мир боли в худшем случае.

Вы должны посмотреть на это из сценария защиты в глубину. То, к чему это сводится, - это разница между черным списком (что пользователю не разрешено делать) и «белым списком» (что должен делать этот пользователь). Хорошие методы безопасности основаны исключительно на последнем методе мышления, потому что невозможно составить полностью исчерпывающий черный список, который охватывает все возможные сценарии.

В таком случае, если вы хотите, чтобы пользователь мог скачивать файлы, вам нужен какой-то список файлов, которые разрешено загружать. Одним из примеров является размещение любого файла, который должен быть загружен в конкретный каталог. Если пользователь запрашивает файл, ваш скрипт может использовать realpath(), чтобы убедиться, что файл находится в вашем общем каталоге и в противном случае запретить загрузку. Хотя, если все они находятся в одном каталоге, вы можете так же легко изменить правило конфигурации на своем веб-сервере (например, apache или nginx), чтобы автоматически добавить заголовок «content-disposition: attachment» к чему-либо в этом каталоге. Тогда вам просто нужно убедиться, что вы никогда не помещаете неправильные файлы в этот общий каталог.

Мне лично, хотя я бы подошел к нему с полным белым списком. Я бы никогда не дал кому-то указать имя файла, а затем использовать его для загрузки файла. Скорее я бы имел административную область, где я управляю файлами, которые помечены для загрузки: список разрешенных файлов будет храниться в базе данных и управляться мной. Когда пользователь загружает файл, он не делает этого, указав имя файла, а указывая идентификатор из базы данных, которая соответствует файлу, который они хотят загрузить (для облегчения этого необходим простой пользовательский интерфейс). Идентификатор используется для поиска пути к файлу, и файл можно загрузить безопасно. Затем вы можете хранить файлы в каталогах за пределами общедоступной области своего веб-сайта, чтобы у вас был полный контроль над тем, кто может получить доступ к файлам.

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