Как я могу сказать, что кто-то подделывает тип файла? (PHP) - PullRequest
12 голосов
/ 09 октября 2008

Я программирую что-то, что позволяет пользователям хранить документы и изображения на веб-сервере, которые будут сохраняться и извлекаться позже. Когда пользователи загружают файлы на мой сервер, PHP сообщает мне, какой тип файла основан на расширении. Однако я боюсь, что пользователи могут переименовать zip-файл в somezipfile.png и сохранить его, сохраняя при этом zip-файл на моем сервере. Есть ли какой-нибудь разумный способ открыть загруженный файл и «проверить», чтобы увидеть, действительно ли он имеет указанный тип файла?

Ответы [ 9 ]

18 голосов
/ 09 октября 2008

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

8 голосов
/ 09 октября 2008

Проверьте расширение FileInfo PECL для PHP, которое может сделать магический поиск MIME для вас.

4 голосов
/ 09 октября 2008

Вроде. У большинства типов файлов есть несколько байтов, зарезервированных для их маркировки, так что вам не нужно полагаться на расширение. Сайт http://wotsit.org - отличный ресурс для выяснения этого для определенного типа.

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

Для PNG (http://www.w3.org/TR/PNG-Rationale.html)

Первые восемь байтов файла PNG всегда содержат следующие значения:

(десятичное число) 137 80 78 71 13 10 26 10

(шестнадцатеричный) 89 50 4e 47 0d 0a 1a 0a

(запись ASCII C) \ 211 P N G \ r \ n \ 032 \ n

2 голосов
/ 09 октября 2008

Если вы имеете дело только с изображениями, то getimagesize () должна отличать действительное изображение от поддельного.

$ php -r 'var_dump(getimagesize("b&n.jpg"));'
array(7) {
  [0]=>
  int(200)
  [1]=>
  int(200)
  [2]=>
  int(2)
  [3]=>
  string(24) "width="200" height="200""
  ["bits"]=>
  int(8)
  ["channels"]=>
  int(3)
  ["mime"]=>
  string(10) "image/jpeg"
}

$ php -r 'var_dump(getimagesize("/etc/passwd"));'
bool(false)

Ложное значение getimagesize не является изображением.

2 голосов
/ 09 октября 2008

Многие типы файлов имеют « магические числа » в начале файла, чтобы идентифицировать их. Вы можете прочитать несколько байтов в начале файла и сравнить их со списком известных магических чисел. *

1 голос
/ 04 ноября 2008

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

Например, http://quantumrook.wordpress.com/2007/06/06/hide-a-rar-file-in-a-jpg-file/ (этот конкретный тип сокрытия данных можно легко обойти, загрузив и сохранив в новом файле фактические данные изображения ... другие будут более сложными.)

1 голос
/ 04 ноября 2008

В качестве дополнительного примечания я столкнулся с аналогичной проблемой, когда мне пришлось провести собственную проверку типа. Интерфейс интерфейса моего приложения был сделан во флэш-памяти. Файлы передавались через flash в php-скрипт. Когда я пытался выполнить проверку MIME-типа с использованием php, всегда возвращался тип application / octetstream, потому что он исходил от flash.

Мне пришлось реализовать парадигму типа магических чисел. Я просто создал XML-файл, который содержал тип файла вместе с некоторыми определяющими шаблонами, найденными в начале файла. Когда файл попал на сервер, я сопоставил шаблон с файлом xml, а затем принял или отклонил файл. Я также не заметил реального снижения производительности, которого я ожидал.

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

1 голос
/ 09 октября 2008

Чтобы получить точный ответ о том, как вы можете быстро сделать это в PHP, проверьте этот вопрос: Как мне найти mime-тип файла с php?

1 голос
/ 09 октября 2008

В системе Unix получение вывода из команды 'file' должно предоставить адекватную информацию.

...