MIME Type spoofing
Asked Answered
B

4

16

Checking for mime type in php is pretty easy but as far as I know mime can be spoofed. The attacker can upload a php script with for example jpeg mime type. One thing that comes to mind is to check the file extension of the uploaded file and make sure it matches the mime type. All of this is assuming the upload directory is browser accessible.

Question: Are there any other techniques for preventing "bad files" from getting in with mime type spoofing?

Bricklaying answered 6/11, 2011 at 15:47 Comment(7)
Is your question about mime type spoofing, or do you just want to know how to validate uploaded files to check if they're image files?Campfire
In fact, you shouldn't rely on MIME types and file extension in the first place (and your check, if mime->extension, is also wrong; if I fake mime I can fake even more easily a corresponding file xtension)Jenelljenelle
@CodeCaster: How to make sure the files that the MIME Types of the files uploaded are not spoofed?Bricklaying
@DamienPirsy: What would you rely on? How would you make sure malicious files are not uploaded?Bricklaying
It really depends on the kind of file you need to upload...I'm not big expert, but you can for ex. use getimagesize() for images, or read the first line of a file to check the headersJenelljenelle
This depends on what you are going to do with the files. As long as you don't let them execute on the server, even the most malicious virus code is harmless.Rendarender
@Pekk: I thought about putting .htaccess file in the upload dir. Seems to be the safest way, yet.Bricklaying
S
13

Short answer: No.

Longer answer:

Comparing the extension and making sure that it matches the MIME type doesn't really prevent anything. As was said in the comments, it's even easier to modify a file extension. MIME type and extension are only to be meant as hints, there's no inherent security in them.

Ensuring that incoming files do no harm is very dependent on what your purpose for them is going to be. In your case I understood that you are expecting images. So what you could do is perform some sanity checks first: scan the first couple of bytes to see if the files contain the relevant image header signatures - all relevant image formats have these.

The "signature headers" help you to decide what kind of image format a file tries to impersonate. In a next step you could check if the rest of the contents are compliant with the underlying image format. This would guarantee you that the file is really an image file of that specific format.

But even then, the file could be carefully crafted in a way that when you display the image, a popular library used to display that image (e.g. libpng etc.) would run into a buffer overflow that the attacker found in that library.

Unfortuantely there's no way to actively prevent this besides not allowing any input from the client side at all.

Ster answered 6/11, 2011 at 16:25 Comment(3)
The images were only examples. Would be dealing with PDF files. But I wanted to generalize the question so it would help with other file types tooBricklaying
The principle is always the same. A smart attacker gives you what you expect, but crafts the file in a way that it exploits the most popular libraries used to view the files. For PDF that would mean that they might embed Javascript, videos, again images... the number of options increases drastically with the features provided by the data format. If you (or your clients!) never "execute" (viewing is "executing", too) uploaded content, only then you are safe.Ster
It's possible to get a "safe" image by copying it over into a new image using a library like GD or a tool like ImageMagick. AFAIK, there is no known open exploit for any of these libraries - there used to be one in Windows' GDI but that has been fixed long since. While it's true that in theory, there is no safety, there are ways to deal with files in a safe manner.Rendarender
T
4

Caution - this answer is now obsolete

The documentation for getimagesize explicitly states "Do not use getimagesize() to check that a given file is a valid image.

In case of Images

  • Check the extension with a list of allowed ones (ex. ".jpg", ".jpeg", ".png")
  • Check the uploaded file itself by running getimagesize on the file, it will return FALSE if it's not an image.

Other types of upload

  • Check the allowed extensions (ex. ".pdf")
  • Check that the mime type of the file corresponds to the extension

Sample code:

function getRealMimeType($filename) {
    $finfo = new finfo(FILEINFO_MIME, "/usr/share/misc/magic"); 
    if (!$finfo) {
        echo "Opening fileinfo database failed";
        return "";
    }
    return $finfo->file($filename);
}

See finfo_file documentation.

Tammitammie answered 6/11, 2011 at 16:15 Comment(5)
It does not have to be an image, it can be any kind of file.Bricklaying
I see, let me expand the answer then.Tammitammie
thats great if getimagesize returns false if its not an image :-) very useful for checking id guess but what if extension is spoofed and mime type too?Selachian
The documentation for getimagesize explicitly states "Do not use getimagesize() to check that a given file is a valid image. Use a purpose-built solution such as the Fileinfo extension instead."Numerical
thanks for pointing it out - I've added a warning on top of the answer -- the documentation didn't say that in 2011 -- see errors/exceptions web.archive.org/web/20111224150939/http://php.net/manual/en/…Tammitammie
S
-1

"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

File extension check in order to block dangerous file extensions such as ".php" is the best way to go if files are going to be uploaded somewhere in the "public_html" folder!

Antivirus scan may be a nice alternative because some spoofed files are detected by antivirus!

Soinski answered 17/1, 2021 at 4:40 Comment(0)
D
-8

Check the extension.

<?php

$okFiles = array('jpg', 'png', 'gif');

$pathInfo = pathinfo($filename);

if(in_array($pathInfo['extension'], $okFiles)) {
    //Upload
} 
else {
    //Error
}

?>

You can also - like you said - check if the extension match the MIME type, but it's much more easy to just check the extension.

Btw why do you care about the MIME type?

Detective answered 6/11, 2011 at 16:12 Comment(3)
to make sure the uploaded file is what it appears to be. Imagine: Upload MIME image but with ext php and php code inside; the upload dir is browser accessible and well as I imagine the attacker could freely run some malicious code.Bricklaying
@Bricklaying So you don't need to check the MIME type at all. Just check the extension. If it's jpg / png / gif it's okay, else throw a error "Just jpg / png / gif". Dont know if this is what you are afraid of but if the extension is .jpg and the MIME sais PHP it will still be treated as a image when you browse to the file.Detective
Also considered that. Just trying to make sure I'm on the right track.Bricklaying

© 2022 - 2024 — McMap. All rights reserved.