Я программирую что-то, что позволяет пользователям хранить документы и изображения на веб-сервере, которые будут храниться и извлекаться позже. Когда пользователи загружают файлы на мой сервер, PHP сообщает мне, какой тип файла он основан на расширении. Тем не менее, я боюсь, что пользователи могут переименовать zip файл как somezipfile.png и сохранить его, тем самым сохраняя zip файл на моем сервере. Есть ли разумный способ открыть загруженный файл и "проверить", чтобы убедиться, что он действительно относится к указанному типу файлов?
Как я могу сказать, если кто-то подделывает файл? (PHP)
Ответ 1
Магический номер. Если вы можете прочитать первые несколько байтов двоичного файла, вы можете узнать, что это за файл.
Ответ 2
Посмотрите FileInfo Расширение PECL для PHP, которое может выполнять MIME-макеты для вас.
Ответ 3
Сорт. Большинство типов файлов имеют некоторые байты, зарезервированные для их маркировки, поэтому вам не нужно полагаться на расширение. Сайт http://wotsit.org - отличный ресурс для поиска этого для определенного типа.
Если вы находитесь в системе unix, я считаю, что команда файла не полагается на расширение, поэтому вы можете отключить его, если вы не хотите писать код проверки байта.
Для 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
Ответ 4
Многие типы файлов имеют " магические числа" в начале файла для их идентификации. Вы можете прочитать несколько байтов с фронта файл и сравнить их со списком известных магических чисел.
Ответ 5
Если вы имеете дело только с изображениями, то 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)
Значение false из getimagesize не является изображением.
Ответ 6
В unix-системе захват вывода из команды "файл" должен содержать соответствующую информацию.
Ответ 7
Для получения точного ответа о том, как вы могли бы быстро это сделать в PHP, проверьте этот вопрос: Как найти тип файла mime с php?
Ответ 8
В качестве побочной заметки я столкнулся с аналогичной проблемой, когда мне приходилось выполнять собственные проверки типов. Интерфейс интерфейса для моего приложения был выполнен во флэш-памяти. Файлы передавались через flash на php script. Когда я пытался выполнить проверку типа MIME с использованием php, возвращаемый тип всегда был application/octetstream, потому что он исходил от флэш-памяти.
Мне пришлось реализовать парадигму типа магических чисел. Я просто создал xml файл, в котором был сохранен тип файла, а также некоторые шаблоны определения, найденные в начале файла. После того, как файл достиг сервера, я сделал некоторый шаблон, соответствующий файлу xml, а затем принял или отклонил файл. Я не заметил никакого реального снижения производительности, которого я ожидал.
Это просто примечание для всех, кто может использовать флеш-память, так как есть передняя часть и пытается ввести проверку файла после его загрузки.
Ответ 9
Помимо идентификации типа файла, вы можете захотеть следить за файлами с другими встроенными или добавленными к ним файлами. Это, к сожалению, потребует более глубокого анализа содержимого файла, чем просто использование "магических чисел".
Например, http://quantumrook.wordpress.com/2007/06/06/hide-a-rar-file-in-a-jpg-file/ (этот конкретный тип скрытия данных можно легко обойти, загрузив и сохранив в новый файл фактические данные изображения.. другим будет сложнее.)