I try to write a upload form and I want user to sent only image or pdf file. To detect mime type I use finfo
but it's really easy to mess with him here an example
<?php
$cnt ='<form action="" method="get">\x0aCommand: <input type="text" name="cmd" /><input type="submit" value="Exec" />\x0a</form>\x0aOutput:<br />\x0a<pre><?php passthru($_REQUEST["cmd"], $result); ?></pre>\x0a';
echo $cnt."\n";
$finfo = new \finfo(FILEINFO_MIME);
echo $finfo->buffer($cnt) . "\n"; // text/plain; charset=us-ascii
$cnt ="\xff\xd8\xff\xe0\x0a".$cnt; // adding random utf8 char at the begining
echo $cnt."\n";
$finfo = new \finfo(FILEINFO_MIME);
echo $finfo->buffer($cnt) . "\n"; // image/jpeg; charset=iso-8859-1
Does any body know how to do it properly ?
Update:
Ok so let's reveal the magic trick : finfo
like many or tool ( cmd file
on unix for example) use a "magic table" to find out which kind of file is it. Look at those example
Short version finfo
search for a series of specific bytes in the stream and if it found it, it return the mime type associated with those number.
To trick it, you just have to had those bytes in your file...
Which does not answer the question on how to find out properly...
There are a few methods to improve file security;
The most effective for images is to convert the image in PHP into another format such as from JPEG to PNG, and then reload it (in PHP memory) and convert it back to the desired format.
If the original image code is malformed (as you example) it will not successfully convert; this will be detected by PHP (as false
or similar).
There are additional parallel test you can do such as using getimagesize
to check the values returned correlate with expected values from the original file and from the converted file etc.
If an image, a vague process could be:
finfo
MIME type (as you already do)JPG --> PNG
).getimagesize
). Remember these.PNG --> JPG
).getimagesize
) compare with values from above.This can't apply to PDF but can ensure images are genuine and also can remove potentially dangerous metadata from JPG images by converting them to PNG and then back to JPG again.
This post might also be useful to you re PDF
Essentially, files are only going to be blocks of data and to this extent MIME type checks (in isolation) will never be a surefire way of promising the file is "genuine". MIME type is like the cover of a book; the cover looks like a literary masterpiece, but until you flick through the pages and find it's all 1980s pornography you won't be sure.
Some useful links: