Загрузка файла PHP: подтверждение на mime или расширение?

Когда я пытаюсь обработать загрузку файла, должен ли я запускать проверку на основе типа файла MIME или расширения файла?

Каковы преимущества и недостатки этих двух способов проверки файлов?

И, Любые другие проблемы безопасности, о которых я должен беспокоиться?

В эти дни я полагался на MIME-тип, но ответ с большинством голосов в этом сообщении

Проблемы с загрузкой файлов в PHP говорят:

Никогда не полагайтесь на MIME-тип, предоставляемый браузером!

Хорошо, поэтому всем гениальным существам, которые здесь что-то рассказывают о «ВИНТОВЫХ РАСШИРЕНИЯХ, ПРОВЕРЯЙТЕ MIME! FILEINFO RLZ!», Я подготовил несколько уроков:

  1. Загрузите этот симпатичный логотип php, который я нарисовал
  2. Посмотрите. Довольно приятно, не так ли?
  3. Переименуйте его в any_you_like.php
  4. Поместите это через весь ваш удивительный тип mime / любые шашки
  5. Запустить его

В заключение вы НИКОГДА НИКОГДА НИКОГДА не полагайтесь на тип MIME. Вам веб-сервер не заботится о типе MIME, он определяет, что делать с помощью EXTENSION , в конечном счете, downvoted @Col. Ответ Шрапнеллы на самом деле прав. Любая информация, предоставленная вам проверкой MIME, абсолютно не имеет отношения к вашему веб-серверу, когда дело доходит до исполнения.

РЕДАКТИРОВАТЬ: не-как-необычный-код-как-вы-хотите-он-быть, который открывает сайт для такого типа атаки:

<?php $mimetype = mime_content_type($_FILES['file']['tmp_name']); if(in_array($mimetype, array('image/jpeg', 'image/gif', 'image/png'))) { move_uploaded_file($_FILES['file']['tmp_name'], '/whatever/something/imagedir/' . $_FILES['file']['name']); echo 'OK'; } else { echo 'Upload a real image, jerk!'; } 

Ни один не подходит для точного определения типа файла. Причины – * Расширение – пользователь может легко изменить расширение, просто переименовав файл. * Тип Mime. Чтобы изменить тип mime, некоторые дополнения или расширения могут делать это, поскольку они поступают с клиентской стороны (поэтому их можно изменить перед отправкой на сервер), а не сгенерировать сервер.

Теперь для проверки ответ на вопрос зависит от того, почему вы хотите проверить тип файла.

В большинстве случаев нам нужно убедиться, что загруженный файл не должен выполняться. По этой причине вы должны быть уверены в том, как ваш сервер обрабатывает / выполняет файлы. – Если ваш сервер проверяет расширения для проверки, вам также необходимо проверить, что вы не храните файл с расширением, которое может быть выполнено. – Если ваш сервер использует mime-типы, остерегайтесь того факта, что mime-тип, отправленный клиентом, и тип mime, используемые сервером для одного и того же файла, могут быть разными. Поэтому используйте ту же логику, что и ваш сервер, чтобы узнать тип mime.

Mime-type не является надежным источником, поскольку он отправляет из браузера (также каждый может создать HTTP-запрос вручную). PHP не проверяет эквивалентность расширения и типа мины (http://ru.php.net/manual/en/features.file-upload.post-method.php). Вы можете указать HTTP-запрос с именем файла image.php и mime-type «image / gif».

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

Чтобы точно определить, что было загружено, вы не проверяете расширение файла или тип mime, отправленный браузером .

В среде * nix у вас есть утилита для проверки типа mime данного файла, обычно находящегося в файле magic.mime (/usr/share/magic.mime или что-то подобное, в зависимости от вашей установки).

Скопируйте / вставьте из magic.mime, чтобы увидеть, как это работает в двух словах:

 # Magic data for KMimeMagic (originally for file(1) command) # # Note on adding additional MIME types: # # [RFC2045,RFC2046] specifies that Content Types, Content Subtypes, Character # Sets, Access Types, and conversion values for MIME mail will be assigned and # listed by the IANA. # http://www.iana.org/assignments/media-types/ # # Any unregistered file type should be listed with a preceding x-, as in # application/x-foo (RFC2045 5.1), or a x., as in application/x.foo (RFC4288 # 4.3). Any non x-prefixed type should be registered with IANA and listed at # the above address. Any other behavior is a MIME standards violation! # # It is preferred that when a registered MIME type exists, that # the registered Content-Type and Subtype be used to refer to a file of # that type, so don't use application/x-zip when application/zip is # registered. # # If an active RFC suggests that a MIME registration for a new type is in # progress, make a note of it pointing to that RFC. # # The format is 4-5 columns: # Column #1: byte number to begin checking from, ">" indicates continuation # Column #2: type of data to match # Column #3: contents of data to match # Column #4: MIME type of result # Column #5: MIME encoding of result (optional) 

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

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

Fileinfo