Some years ago there was an opinion, that $_FILES[$file]['type'] contains mimetype sent from a browser, but not real mimetype, for example here:
http://php.net/manual/ru/reserved.variables.files.php#109902
Is it still so and do i still need to use fileinfo extension to detect mimetype?
(i am using php5.4)
Yes, type is populated with data provided by the browser.
From the manual page about POST method uploads:
$_FILES['userfile']['type']
The mime type of the file, if the browser provided this information. An example would be "image/gif". This mime type is however not checked on the PHP side and therefore don't take its value for granted.
Yes, that's still the case. The type is the client-provided MIME information.
I always use fileinfo for this, but if you use a flash uploader maybe you will find that almost every file uploaded with the flash uploader is detected as application/octet-stream.
Because this... I also have a "mimetype detection from extension" method that, in case the file is detected as application/octet-stream by fileinfo, it will check it's extension and try to determine the real file type.
Related
I'm confusing because some .mp3 files can't pass my validation:
mimes:mpga
var_dump of this files looks the same with files that successfuly passed validation, they all have the same mimeType -mimeType: "audio/mp3"
I've tryed to extend validation rule but that's doesn't work: mimes:mpga,audio/mpeg,audio/mp3
Here is the track that can't pass http://dropmefiles.com/L1iGQ
UPD
$file->getErrorMessage() returns The file "Emmanuelle - Italove.mp3" was not uploaded due to an unknown error.
And that makes me cry because in real life there is no problems with saving this track if not using validation
In my opinion, you should not rely for MIME type if you want to validate uploaded file. My arguments are:
MIME type is used in web primarily to tell browser what content it should expect, so the browser could render/process it properly. It sorts of serve the function of file extension in the web. But the problem is, a particular file type doesn't have one-to-one relationship with their MIME type. So if you try to only allow a particular file extension based on their MIME type, you might get unexpected result. you could check here: list of file extension vs mime
On top of that, if you do try to upload a file from a browser, and let browser decide what MIME type it should attach, you may also get different result, depending on the browser that sends it (e.g. Firefox would give mp3-> audio/mpeg; while Chrome would give mp3-> audio/mp3) type check.
So my advice is to just use validation based on the given extension, if your intention is to only allowing mp3 file to be uploaded.
I read a lot of articles (including this) talking about secure file upload in PHP and I think this is the best way to make sure the file uploaded is safe.
First, I use mime_content_type() to check its file's type.
If it is JPG, JPEG or PNG, I'm gonna clone it with imagecreatefromjpg(), if success, save the new file and destroy the original.
I'm not sure this is safe enough or I need to do something else.
I appreciate any help.
TL;DR: mime_content_type checks real file content to detect type
I did some testing for mime_content_type
When I created text file and named it "spoofily" spoof.jpg...the detected mime type was still text/plain
When I ran it on non existing file, it throws
PHP Warning: mime_content_type(not.exist):
failed to open stream: No such file or directory
This means mime_content_type checks file content for mime type.
Is it totally safe though? It is safe enough to detect the true mime type, that's for sure ;)
However you should also check for things like size or sanitizing filename (when reused), for more security details, there is a nice answer on Security Stack: Risks of a PHP image upload form
note that in the PHP manual, this is under "Fileinfo Functions" menu => it kind of implies it uses file-read mechanisms, though it is true manual entry doesn't say this explicitly...
"mime_content_type" and "exif_imagetype" should not be used for security purposes because both of them allow spoofed files!
More details from link below:
https://straighttips.blogspot.com/2021/01/php-upload-spoofed-files.html
I have an upload form which allowed most of file types to be uploaded.
Here they are:
Image: jpg/jpeg/png/gif ...
Video: mp4/avi/wmv ...
another files: doc/pdf/rar/zip/mp3/...
For image file, I know I can use PHP function getimagesize() or something else to make sure it's the real image. But how about the other files such as Video, and documentation ? Is it a real file without faking the extension ?
How to do that?
Thank you! I need your help.
every file has it's own type, it called mime type , so u can check the mime type , do some things like that :
if (mime_content_type($FILES['file']['tmp'])== "image/png"))
{
// do upload
}else{
die('file type not supported');}
u can put all the mime type into an array the check the type with in_array function
u can find all the mime type here : http://www.freeformatter.com/mime-types-list.html
Any client-side check (even the browser mime-type detection) is doomed to fail because user has access to it. You'd better let the upload begin and complete, then perform a serious server side check. You simply discard the file if that is not what you expected to be.
On top of the server-side check you can of course implement the client-side check just for a neater user experience
The only way to fully secure a file upload is to attempt parsing the uploaded file with PHP or some other extension/tool that expects a specific valid file type. In other words:
Images: use GD functions to parse the file, they'll return false if it isn't a valid image.
Videos: could probably validate using ffmpeg on the command line and check the output or use the ID3 extension as suggested here: https://stackoverflow.com/a/134893 (credit to Zathrus Writer's comment on the question linking to this question)
Documents: Attempt loading the file with PHPExcel/Word/PowerPoint although I'm not sure that these would support just any format of those documents as it works on OpenXML.
From looking at the getID3 extension this might be the best bet as it seems to parse a wide variety of content types.
In any case, what you essentially need is for PHP or some other 3rd party library/extension to determine that the binary data of a file corresponds with its MIME content type.
Hope this helps :)
Can we read the header information of a file in PHP to determine the type of file uploaded?.
I don't want to rely on $_FILES['control_name_from_client']['type']. As we know that this property determines the file type by reading the extension of the file uploaded.
What if the user renames, say test.jpg -> test.xls. In that case, $_FILES['control_name_from_client']['type'] will show the type as application/vnd.ms-excel instead of image/jpeg. It is but natural this can create problems if a code has to be executed which reads the XLS file to fetch data for some processing.
Any suggestions please?
Try finfo_file(). You have to call it passing the filepath. Example:
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['control_name_from_client']['tmp_name']);
finfo_close($finfo);
You need the Fileinfo extension. As PHP manual says:
The functions in this module try to guess the content type and encoding of a file by looking for certain magic byte sequences at specific positions within the file. While this is not a bullet proof approach the heuristics used do a very good job.
as far as I'm aware, there is no such function in PHP, but if you have access to the CLI (and are running Linux), you could use the "file" command through system().
There used to be the mime_magic extension in older versions of PHP, but that's deprecated now in favour of finfo_file, which does use file signatures to test the filetype, not purely the extension.
Dunno what "header" you are talking about, but from the security point of view the only thing you really have to pay attention to is a filename extension.
Just because your web-server would judge your file by it.
To test if uploaded file being valid data for some particular application, you have to use this application-specific routine, there are no universal tool in PHP.
you can use imagemagick for images, getid3 for the mp3 files, fffmpeg for the movies and so on.
But of course whole file have to be employed, checking just "header" doesn't guarantee that entire file is valid.
Simple question. Is there a way to only allow txt files upon uploading? I've looked around and all I find is text/php, which allows PHP.
$uploaded_type=="text/php
When you upload a file with PHP its stored in the $_FILES array. Within this there is a key called "type" which has the mime type of the file EG $_FILES['file']['type']
So to check it is a txt file you do
if($_FILES['file']['type'] == 'text/plain'){
//Do stuff with it.
}
It's explained very well here. Also, don't rely on file extentions it's very unreliable.
Simply put: there's no way. Browsers don't consistently support type limiters on file upload fields (AFAIK that was planned or even is integrated into the HTML standard, but barely implemented at best). Both the file extension and mime-type information are user supplied and hence can't be trusted.
You can really only try to parse the file and see if it validates to whatever format you expect, that's the only reliable way. What you need to be careful with are buffer overflows and the like caused by maliciously malformed files. If all you want are text files, that's probably not such a big deal though.
You could check the mime type of the uploading file. In codeIgniter, this code is used in the upload library:
$this->file_type = preg_replace("/^(.+?);.*$/", "\\1", $_FILES[$field]['type']);
The variable $this->file_type then used to check the upload configuration, to see if the uploaded file is in allowed type or not. You can see the complete code in the CodeIgniter upload library file.
You need to check the file extension of the uploaded file.
There is Pear HttpUpload, it supports this.