2008-10-08 3 views
12

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

ответ

18

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

+0

Магические числа не всегда начало. Я думаю, TGA, например, имеет их в конце. – 2008-10-08 23:02:12

+0

помните, что, полагаясь на эту проверку, злоумышленники могут вставлять магические байты, а затем писать PHP-код в том же файле, чтобы попытаться выполнить код на вашем компьютере. – Jorre 2012-12-04 13:53:03

4

Сорт. Большинство типов файлов имеют некоторые байты, зарезервированные для их маркировки, поэтому вам не нужно полагаться на расширение. Сайт 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 PNG \ г \ п \ 032 \ п

2

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

1

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

8

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

2

Если дело только с изображениями, то 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 - это не изображение.

1

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

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

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

1

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

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

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