Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP file upload: mime or extension based verification?

When I try to process file upload, should I run verification based on file MIME type or file-extension?

What are Pros & cons of these 2 ways of file validating?

And, Any other security issues should i be concerned of?

In these days I was relying on MIME type but the answer with most up-votes in this post

File upload issues in PHP says:

Never rely on the MIME type submitted by the browser!

like image 594
Shafiul Avatar asked Sep 08 '11 14:09

Shafiul


2 Answers

Okay, so to all the geniouses here yapping something about "SCREW EXTENSIONS, CHECK MIME! FILEINFO RLZ!", I've prepared some tutorial:

  1. Download this pretty php logo I drew
  2. View it. Pretty nice, isn't it?
  3. Rename it to whatever_you_like.php
  4. Put it through all your awesome mime type/whatever checkers
  5. Run it

In conclusion, you should NEVER EVER EVER rely on MIME type. You web server doesn't care about MIME type, it determines what to do by EXTENSION, the ultimately downvoted @Col. Shrapnel's answer is actually right. Any information provided to you by something checking MIME is absolutely irrelevant to your webserver when it comes to execution.

EDIT: the not-as-uncommon-code-as-you'd-want-it-to-be that opens a website to this type of attack:

<?php

$mimetype = mime_content_type($_FILES['file']['tmp_name']);
if(in_array($mimetype, array('image/jpeg', 'image/gif', 'image/png'))) {
   move_uploaded_file($_FILES['file']['tmp_name'], '/whatever/something/imagedir/' . $_FILES['file']['name']);
   echo 'OK';

} else {
    echo 'Upload a real image, jerk!';
}
like image 174
cypher Avatar answered Sep 18 '22 14:09

cypher


In order to accurately determine what has been uploaded, you don't check for the file extension nor for the mime type sent by browser.

On *nix environment, you've got the utility for checking the mime type of a given file, usually located in magic.mime file (/usr/share/magic.mime or something similar, depending on your setup).

Copy/paste from the magic.mime so you see how it works in a nutshell:

# Magic data for KMimeMagic (originally for file(1) command)
#
# Note on adding additional MIME types:
#
# [RFC2045,RFC2046] specifies that Content Types, Content Subtypes, Character
# Sets, Access Types, and conversion values for MIME mail will be assigned and
# listed by the IANA.
# http://www.iana.org/assignments/media-types/
#
# Any unregistered file type should be listed with a preceding x-, as in
# application/x-foo (RFC2045 5.1), or a x., as in application/x.foo (RFC4288
# 4.3).  Any non x-prefixed type should be registered with IANA and listed at
# the above address.  Any other behavior is a MIME standards violation!
#
# It is preferred that when a registered MIME type exists, that
# the registered Content-Type and Subtype be used to refer to a file of
# that type, so don't use application/x-zip when application/zip is
# registered.
#
# If an active RFC suggests that a MIME registration for a new type is in
# progress, make a note of it pointing to that RFC.
#
# The format is 4-5 columns:
#    Column #1: byte number to begin checking from, ">" indicates continuation
#    Column #2: type of data to match
#    Column #3: contents of data to match
#    Column #4: MIME type of result
#    Column #5: MIME encoding of result (optional)

I'll link you with a link that'll help you in further implementation in PHP (literally 2 lines of code once you're done).

If you can't make it work after all of this, post here in comments and I'll provide full code needed to safely detect what has been uploaded.

Fileinfo

like image 24
N.B. Avatar answered Sep 20 '22 14:09

N.B.