2009-03-03 2 views
1

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

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

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

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

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

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

ответ

6

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

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

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

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

+0

Спасибо за ответ bobince! Это хорошее решение, но я обеспокоен переносимостью данных, так как простая резервная копия файлов подразумевает запуск некоторого сценария сначала для изменения схемы именования, и если моя база данных когда-либо будет скомпрометирована или повреждена, я проиграю структура древовидной структуры. – lima

+0

Хорошее решение. @fandelost, затем убедитесь, что вы резервны как базы данных, так и файлы –

+0

Прошу прощения за то, что ответили так долго. Я, наконец, подал в отставку «AjaxExplorer» и создал собственное решение для управления файлами, основанное на совете bobince, используя базу данных для хранения всего, что связано с файлами, но не трогало их после того, как они загружены за пределы корня веб-сайта. Я также ограничил поле «имя» для каждого из них ограниченным набором символов, и я не буду использовать вложенные папки, вместо этого я использую один уровень группировки (просто чтобы избежать ссылочного беспорядка). – lima

0

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

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

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

0

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

$destdir = str_replace(array('.', '/', '\\'), '', $_POST['destination_dir']); 
$destdir .= "/"; 
+0

Строка со всеми недопустимыми символами сопоставляется с корневой папкой сервера. – bobince

+0

Спасибо за ответ, однако точки AFAIK, косые черты и обратные косые черты - все допустимые символы для именования папки, по крайней мере, в мире * NIX. – lima

+0

Не так верно bobince, так как я могу добавить путь, но я не буду использовать это решение в любом случае. – lima

Смежные вопросы