Защита файлового менеджера PHP от его пользователей

StackOverflow https://stackoverflow.com/questions/608112

Вопрос

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

Я уже внедрил стороннее решение для аутентификации для CI (Повторная аутентификация 2 Бета-версии) и сейчас я интегрирую файловый менеджер JS / PHP (AjaxExplorer), но проблема в том, что серверная часть PHP для управления файлами (перемещение, копирование и т.д.) Слишком сильно доверяет пользовательскому вводу из вызовов ajax.Например, он делает такие вещи, как это (упрощено для большей ясности):

move_uploaded_file($_FILES['upload']['tmp_name'], $root.$username.$_POST['destination_dir']);

Как вы можете видеть, существуют очевидные проблемы с безопасностью, поскольку он слепо принимает любой путь, который вводит пользователь!Я уже вижу, что кто-то отправляет что-то вроде "../AnotherUser/" в качестве значения $_POST['destination_dir'].

Мой вопрос заключается в следующем: Каков наилучший способ "изолировать" пользователя, чтобы позволить ему управлять только своими собственными данными? Должен ли я просто проверять + фильтровать входные данные, надеясь перехватить каждую попытку вторжения?Существуют ли какие-либо библиотеки / пакеты, предназначенные для решения этой конкретной проблемы?

Я думаю, что эта проблема должна быть каким-то образом решена в любом (достаточно зрелом) проекте, который дает своим пользователям возможность управлять своими файлами через веб-браузер, поэтому я ожидал найти какие-то четкие рекомендации по этому поводу (поскольку там много о SQL-инъекциях, XSS, CSRF и т.д.), Но, думаю, я использую не те ключевые слова.

Это было полезно?

Решение

Каков наилучший способ "изолировать" пользователя, чтобы позволить ему управлять только своими собственными данными?

Разрешайте любые имена файлов / каталогов по желанию пользователя, но просто не используйте их в файловой системе на стороне сервера.Вместо этого запишите имена путей в базу данных с первичным ключом и используйте первичный ключ как имя файла, например ‘34256.dat’, в плоском каталоге хранения (или даже как большой двоичный объект в базе данных, если хотите).Затем выполните загрузку с помощью скрипта загрузки или перепишите URL-адрес, чтобы в URL-адресе отображалось желаемое имя файла.

Очистка входящих имен файлов - это жесткий.Обнаружение ‘..’ - это только начало.Слишком длинные имена файлов;слишком короткие имена файлов;комбинации начальных и завершающих точек;комбинации начальных и завершающих пробелов;различные разделители каталогов для разных платформ;символы, которые недопустимы на некоторых платформах;управляющие символы;Символы Юникода и способы обращения к ним в зависимости от среды;ADSs;имена файлов (‘.htaccess’) или расширения (‘.php’, ‘.cgi’), которые могут быть ‘особенными’ для вашего веб-сервера;Зарезервированные имена файлов Windows...

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

Другие советы

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

//$_POST['destination_dir'] = '4hg43h5g453j45b3';
*_query('SELECT dir FROM destinations WHERE key = ? LIMIT 1'); //etc.

Однако вы должны заранее определить ключи перед раздачей.Другой альтернативой могло бы быть обратное:md5 / sha1 введите и используйте это как destination_dir , затем сохраните этот ключ в базе данных с соответствующей меткой.

Насколько мне известно, нет ни одной библиотеки.
Однако в вашем конкретном примере удалите все (обратные) косые черты и точки из строки, а затем добавьте косую черту в ее конец, чтобы пользователь не мог изменять папки.

$destdir = str_replace(array('.', '/', '\\'), '', $_POST['destination_dir']); 
$destdir .= "/";
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top