Jump to content

How MIME Type works?


doubledee

Recommended Posts

Not sure if I used the right title?!

 

This question is based on some other threads about uploading User Pictures to my website.

 

Questions:

1.) If there is a file which is actually a photograph, but it is named "SomePhoto.xls" then what will happen?

 

2.) If there is a file which is actually a PHP script, but it is named "AnotherPhoto.jpg" then what will happen?

 

3.) If there is a file which is actually a Spreadsheet, but it is named "YetAnotherPhoto.png" then what will happen?

 

In other words, what is the "driving" factor here...  The file's true contents OR simply the file's name and extension?

 

Thanks,

 

 

Debbie

 

Link to comment
Share on other sites

Did you try 1 & 3?

 

I got a naked picture of Justin Bieber...  What should I do??  :o

 

 

Um, I asked because last night I had a file with PHP inside of it and yet labeled as an image (i.e. "test.php.jpg") and it ran as PHP...

 

 

Have you created a small test script for uploading images?

 

I'm working on it slowly if I can get some help here...  ;)

 

It has been implied by others that I just rename any uploaded files, but I am wondering what would happen if a "bad" file slipped through my code checks and I renamed it from "really_an_evil_exe.jpg" to "1234.jpg" and then opened it later?!

 

Here is what I have so far to check if a file is "valid", but I'm not sure how reliable my code is...

// Determine if Photo was uploaded via HTTP POST.
if (is_uploaded_file($_FILES['userPhoto']['tmp_name'])){
	// File uploaded via HTTP.

	// Check File Type.
	if ($_FILES["userPhoto"]["type"] !== 'image/gif'
			&& $_FILES["userPhoto"]["type"] !== 'image/jpeg'
			&& $_FILES["userPhoto"]["type"] !== 'image/png'){
		// Not Image File.			
		$errors['upload'] = 'File-type must be either GIF, JPG, or PNG';
	}else{
		// Valid Image File.
		// Continue processing...
	}
}else{
	// Invalid upload method.
	$errors['upload'] = 'Invalid upload.  Try again.';
}

 

Not sure how "hackable" this could be?

 

 

Debbie

 

 

Link to comment
Share on other sites

In other words, what is the "driving" factor here...  The file's true contents OR simply the file's name and extension?

 

There isn't really any single factor, however most software uses the extension as the determining factor.  For instance when you upload your excel document that is named 'somefile.jpg' the browser will likely report it as a image/jpeg type.

 

Some software will actually attempt to guess the mime type by examining the contents of the file.  For example, IE does this I believe.  PHP's getimagesize will do it to some extent and there is a library out there people can use to do this.  It looks for special marks that exist only in certain formats in the contents of the file.

 

 

Um, I asked because last night I had a file with PHP inside of it and yet labeled as an image (i.e. "test.php.jpg") and it ran as PHP...

 

This is because apache takes into account all the extensions when deciding what to do with a file.  "test.php.jpg" has two extensions:

.jpg which tells apache it is an image/jpg file (the mime type) and

.php which tells apache it needs to be processed using the php handler.

 

Most software is only concerned with the right-most extension, in this case .jpg, and would treat it as an image.

 

 

It has been implied by others that I just rename any uploaded files, but I am wondering what would happen if a "bad" file slipped through my code checks and I renamed it from "really_an_evil_exe.jpg" to "1234.jpg" and then opened it later?!

 

Not sure how "hackable" this could be?

 

It look ok so far.  I would recommend not checking the $_FILES['userPhoto']['type'] key and instead check the results of calling getimagesize() on the file.  The type set in that key is whatever the browser sent which could be a number of things.  For instance, I've seen a JPEG image report as any of:

image/jpeg

image/jpg

image/p-jpeg

image/p-jpg

 

getimagesize will provide a more reliable test because it actually checks the file's content not the extension.

 

Link to comment
Share on other sites

In other words, what is the "driving" factor here...  The file's true contents OR simply the file's name and extension?

 

There isn't really any single factor, however most software uses the extension as the determining factor.  For instance when you upload your excel document that is named 'somefile.jpg' the browser will likely report it as a image/jpeg type.

 

Some software will actually attempt to guess the mime type by examining the contents of the file.  For example, IE does this I believe.  PHP's getimagesize will do it to some extent and there is a library out there people can use to do this.  It looks for special marks that exist only in certain formats in the contents of the file.

 

So it is not enough to just check the File Extension of a file that a User uploaded, right?

 

Is this code enough to determine the true contents of an Uploaded File...

		// Check File Type.
		if ($_FILES["userPhoto"]["type"] !== 'image/gif'
				&& $_FILES["userPhoto"]["type"] !== 'image/jpeg'
				&& $_FILES["userPhoto"]["type"] !== 'image/png'){
			// Not Image File.			
			$errors['upload'] = 'File-type must be either GIF, JPG, or PNG';
//				$errors['upload'] = 'File-Type must be either gif, jpg, or png';
		}else{
			// Valid Image File.
			// Continue processing...
		}

 

 

Um, I asked because last night I had a file with PHP inside of it and yet labeled as an image (i.e. "test.php.jpg") and it ran as PHP...

 

This is because apache takes into account all the extensions when deciding what to do with a file.  "test.php.jpg" has two extensions:

.jpg which tells apache it is an image/jpg file (the mime type) and

.php which tells apache it needs to be processed using the php handler.

 

Most software is only concerned with the right-most extension, in this case .jpg, and would treat it as an image.

 

That is what I would have guessed too.

 

Apparently Apache is more aggressive and looks at all apparent extensions in the file name?

 

Does Apache also inspect the File Contents in order to decide which Handler to launch?

 

 

 

It has been implied by others that I just rename any uploaded files, but I am wondering what would happen if a "bad" file slipped through my code checks and I renamed it from "really_an_evil_exe.jpg" to "1234.jpg" and then opened it later?!

 

Not sure how "hackable" this could be?

 

It look ok so far.  I would recommend not checking the $_FILES['userPhoto']['type'] key and instead check the results of calling getimagesize() on the file.  The type set in that key is whatever the browser sent which could be a number of things.  For instance, I've seen a JPEG image report as any of:

image/jpeg

image/jpg

image/p-jpeg

image/p-jpg

 

getimagesize will provide a more reliable test because it actually checks the file's content not the extension.

 

Should I do both or just skip to getImageSize()??

 

Also, I thought I read some places that getImageSize() can be tricked?

 

Thoughts?

 

Thanks,

 

 

Debbie

 

Link to comment
Share on other sites

Here is a quick test I did (2 mins)..

created a file

<?PHP
echo "Hello World!";
?>

named it helloworld.jpg

uploaded it to my wbesite

pointed my browser to it

the result - http://www.nstoia.com/helloworld.jpg

 

I asked because I cannot test or know all outcomes.

 

I created a test.jpg file with the contents "This is some PHP code" (10 seconds) and got different outcomes between Preview on my Mac and opening it and on my website.

 

And FYI, I spent2-3 weeks building and TESTING my User Accounts module all by my lonesome, so, yes, I do know how to try things out myself.  I also know when I should ask for help.  And you also don't seem to understand that I get lonely and just like talking to others also...  ;)

 

 

Debbie

 

Link to comment
Share on other sites

Apparently Apache is more aggressive and looks at all apparent extensions in the file name?

It looks at each extension because each extension can provide different information.  For example you could do something like: index.php.html.en and apache would deduce from the extensions that:

- It's a text/html mime type

- It needs run through the PHP handler

- It's in the english language.

 

Multiple extensions aren't really all that useful when dealing with a dynamic page such as a php page though, so it's better to configure the server to only use php if the final extension is .php.  Some servers are not configured in this manner though so it opens up issues.

 

Does Apache also inspect the File Contents in order to decide which Handler to launch?

No, only the extensions.

 

 

 

Should I do both or just skip to getImageSize()??

As I already said:

I would recommend not checking the $_FILES['userPhoto']['type'] key

 

 

Also, I thought I read some places that getImageSize() can be tricked?

No, getimagesize will ensure it is a valid image, and it will tell you what type it is (jpeg, gif, or png).  What it won't do is prevent someone from inserting PHP into the image in such a way that the image remains valid.  Such as in the meta-data fields.

 

That is why you take the extra step of making sure the code wont execute if someone does put it in there.

 

 

Unrelated Side note: you should use the preview option before posting and make sure you get all your quote's correct.  It makes it harder to read and understand your posts when you have people's quoted text mixed in with your own because the tags are messed up.

 

Link to comment
Share on other sites

Kicken,

 

I am reading up on getImageSize() now...

 

 

------

Unrelated Side note: you should use the preview option before posting and make sure you get all your quote's correct.  It makes it harder to read and understand your posts when you have people's quoted text mixed in with your own because the tags are messed up.

 

I almost always do.  Why, where did I mess up?  My last few posts look okay?  Link to poorly formatted post?

 

Thanks for everyone's help so far!!

 

 

Debbie

 

Link to comment
Share on other sites

One thing that hasn't been pointed out yet:

$_FILES[foo]["type"] is not secure because it is provided by the browser, not by PHP. You need to figure the type out by yourself (like with getimagesize()).

 

Actually kicken mentioned that earlier..

I would recommend not checking the $_FILES['userPhoto']['type'] key and instead check the results of calling getimagesize() on the file.  The type set in that key is whatever the browser sent which could be a number of things.  For instance, I've seen a JPEG image report as any of:

image/jpeg

image/jpg

image/p-jpeg

image/p-jpg

 

 

Since you bring it up again, though, maybe you can help me figure things out...

 

I am unclear of how to access the getImageSize array?!  :shrug:

 

First off, when I look in the manual it is strange the indices they use on the array.  The manual says...

Returns an array with 7 elements.

 

Index 0 and 1 contains respectively the width and the height of the image.

 

    Note:

    Some formats may contain no image or may contain multiple images. In these cases, getimagesize() might not be able to properly determine the image size. getimagesize() will return zero for width and height in these cases.

 

Index 2 is one of the IMAGETYPE_XXX constants indicating the type of the image.

 

Index 3 is a text string with the correct height="yyy" width="xxx" string that can be used directly in an IMG tag.

 

mime is the correspondant MIME type of the image. This information can be used to deliver images with the correct HTTP Content-type header:

 

 

However, var_dump() says this...

array
  0 => int 1090
  1 => int 530
  2 => int 3
  3 => string 'width="1090" height="530"' (length=25)
  'bits' => int 8
  'mime' => string 'image/png' (length=9)

 

I would expect that the Image's Type is on position [2].

 

Also, I would expect [ 0 ] through [7]...

 

What is up with that?!

 

 

Debbie

 

Link to comment
Share on other sites

Using list would do the trick:

 

list($width, $height, $type) = getimagesize($_FILES['userPhoto']['tmp_name']);

That is how I do it anyhow :)

 

Regards, PaulRyan.

 

Except if you look at my var_dump() above I get this...

array
  0 => int 1179
  1 => int 525
  2 => int 3
  3 => string 'width="1179" height="525"' (length=25)
  'bits' => int 8
  'mime' => string 'image/png' (length=9)

 

I would expect this...

array
  2 => 'image/png'

 

 

Also, why is it if I select my "test.php.jpg" file, I get this error...

Notice: getimagesize() [function.getimagesize]: Read error! in /Users/user1/Documents/DEV/++htdocs/05_Debbie/members/upload.php on line 56

 

Here is a snippet of my code...

	$tempName = $_FILES['userPhoto']['tmp_name'];

	// Determine if Image was uploaded via HTTP POST.
	if (is_uploaded_file($tempName)){
		// File uploaded via HTTP.

		// Get of Image Details.
		$imageDetails = getImageSize($tempName);

		// Get Image Type
		$imageType = $imageDetails['mime'];

echo '<p>var_dump($imageDetails) = ' . var_dump($imageDetails) . '</p>';

echo '<p>var_dump($imageType) = ' . var_dump($imageType) . '</p>';

 

Where Line 56 starts here: $imageDetails = getImageSize($tempName);

 

(The var_dump() shows

boolean false
below the error message, but that shouldn't break anything?!)

 

 

Debbie

 

Link to comment
Share on other sites

Because it's not an image, so it returns false.

 

But that's circular logic I've been told to use...

 

I am using getImageSize() to determine what TYPE the File is, and if this function pukes when it is not an Image then how am I supposed to know it is not an Image?!  (I was under the impression that the function returned FALSE if it was not an Image.)

 

So what is the solution??

 

I need a function that tells me the File Type including if it is NOT an Image.

 

Any suggestions?

 

 

Debbie

 

Link to comment
Share on other sites

I would expect this...

array
  2 => 'image/png'

 

From the manual for getimagesize() under Return Values

Index 2 is one of the IMAGETYPE_XXX constants indicating the type of the image.

 

See the related function exif_imagetype() which lists the numeric number associated with each type (3 == PNG image)

 

Also, why is it if I select my "test.php.jpg" file, I get this error...

Notice: getimagesize() [function.getimagesize]: Read error! in /Users/user1/Documents/DEV/++htdocs/05_Debbie/members/upload.php on line 56

 

Again from the manual for getimagesize(), this time  under Errors/Exceptions

If accessing the filename image is impossible, or if it isn't a valid picture, getimagesize() will generate an error of level E_WARNING. On read error, getimagesize() will generate an error of level E_NOTICE.

 

Although your problem may be a folder issue - the function can and will return errors if you don't pass it an image.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.