Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I tell if someone's faking a filetype? (PHP)

I'm programming something that allows users to store documents and pictures on a webserver, to be stored and retrieved later. When users upload files to my server, PHP tells me what filetype it is based on the extension. However, I'm afraid that users could rename a zip file as somezipfile.png and store it, thus keeping a zip file on my server. Is there any reasonable way to open an uploaded file and "check" to see if it truly is of the said filetype?

like image 947
stalepretzel Avatar asked Oct 08 '08 22:10

stalepretzel


6 Answers

Magic number. If you can read first few bytes of a binary file you can know what kind of file it is.

like image 77
Marko Dumic Avatar answered Nov 20 '22 01:11

Marko Dumic


Sort of. Most file types have some bytes reserved for marking them so that you don't have to rely on the extension. The site http://wotsit.org is a great resource for finding this out for a particular type.

If you are on a unix system, I believe that the file command doesn't rely on the extension, so you could shell out to it if you don't want to write the byte checking code.

For PNG (http://www.w3.org/TR/PNG-Rationale.html)

The first eight bytes of a PNG file always contain the following values:

(decimal) 137 80 78 71 13 10 26 10

(hexadecimal) 89 50 4e 47 0d 0a 1a 0a

(ASCII C notation) \211 P N G \r \n \032 \n

like image 42
Lou Franco Avatar answered Nov 20 '22 00:11

Lou Franco


If you are only dealing with images, then getimagesize() should distinguish a valid image from a fake one.

$ 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)

A false value from getimagesize is not an image.

like image 38
Shoan Avatar answered Nov 20 '22 02:11

Shoan


Check out the FileInfo PECL extension for PHP, which can do the MIME magic lookups for you.

like image 26
Paul Dixon Avatar answered Nov 20 '22 01:11

Paul Dixon


Many filetypes have "magic numbers" at the beginning of the file to identify them, You can read some bytes from the front of the file and compare them to a list of known magic numbers.

like image 2
Nick Avatar answered Nov 20 '22 01:11

Nick


For an exact answer on how you could quickly do this in PHP, check out this question: How do I find the mime-type of a file with php?

like image 1
leek Avatar answered Nov 20 '22 02:11

leek