Do not run someName.php.jpg

This is a scary article: How to block users uploading malware to your blog?

And, well, I confess that I created a test.php.jpg file, uploaded it to my Web Root, and wha-la, I got the phpinfo() in Full-Frontal Nudity!!! :eek: :blush:

I am curious what any Apache experts out there think about this code…


# BEGIN drop-file hack stopper
RemoveHandler application/x-httpd-php .php
<FilesMatch ".(php|php5|php4|php3|phtml|phpt)$">
SetHandler x-httpd-php5
FilesMatch>
<FilesMatch ".phps$">
SetHandler x-httpd-php5-source
</FilesMatch>
# END drop-file hack stopper

I quickly added this code to my .htacess file, and it seems to have solved the problem, but since I am working on a module to let Users upload their Pictures, I am pretty freaked out right now!!! (And wondering if this basic feature is worth threats like this?!) :frowning:

Debbie

DD,

[MODS: this belongs in the PHP forum.]

Regards,

DK

David,

I do not understand what you are saying…

You are missing the key point, which is that the file I FTP’ed to my site executed as a .php file even though it was labeled .jpg

That is an Apache issue, and NOT a PHP issue!!

If someone uploads an exe file (which, presumably, you’ve prevented), then rename it to something else, like XXX.txt. Apache is GREAT at serving files but it’s not designed to protect against foolish programming errors - that’s YOUR job with PHP. There are plenty of good PHP tutorials on file uploads (and security in general) as well as the basic php.net website.
Regards,

DK

All of the articles and sample code I have seen on Uploading Files using PHP are crap!!! (You’d think that such a common practice would have tons of great articles that thoroughly cover security, but I haven’t read any yet?!) :rolleyes:

I am trying to get answers to my PHP issues in the PHP forum, but this thread is 100% about Server Management and Apache…

Debbie

Turns out this code you gave me locks up my entire website…


# BEGIN drop-file hack stopper
RemoveHandler application/x-httpd-php .php
<FilesMatch ".(php|php5|php4|php3|phtml|phpt)$">
SetHandler x-httpd-php5
FilesMatch>
<FilesMatch ".phps$">
SetHandler x-httpd-php5-source
</FilesMatch>
# END drop-file hack stopper

Some Internal Server Error or something…

Debbie

A simple way to test if a file is an image, is getimagesize, do make sure the file exists before calling that.

I’m actually having issues with that right now…


	if ($_SERVER['REQUEST_METHOD']=='POST'){
		// Form was Submitted (Post).

		// Initialize Variables.
		$errors = array();

		// Connect to the database.
		require_once(WEB_ROOT . 'private/mysqli_connect.php');

echo '<br />';

print_r($_FILES);

echo '<br />';

var_dump($_FILES);


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

		echo '<p>$tempName = ' . $tempName . '</p>';

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

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

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


			if ($imageDetails){
			// Get Image Type
			$imageType = $imageDetails['mime'];

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

If I select the file we were talking about (“test.php.jpg”) then I get this error…

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

(Line 56 is: $imageDetails = getImageSize($tempName); )

It is like I have to check if the file is an Image before I can check if the file is an Image?! (:

What is going on?

Debbie

That’s actually correct.

list($w,$h) = @getimagesize($tempName);

if ($w && $h) {
# is an image
}

It is not right!

If the File is NOT an Image then I get this error…

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

I can’t use that function to check if a File is an Image unless I know the FIle is an Image because otherwise getImageSize() pukes…

Debbie

Did you try running my code?

I did, and it worked on my someFile.txt scenario, but I thought I had read that a hacker could alter/spoof the dimensions and thus likely render your suggestion useless?

I guess I’m not feeling very trusting of that approach…

Is the another and/or more reliable way to check the File Type before determining What Image Type it is?

Debbie

I keep making posts here and they aren’t showing up?!

Trying again…

I tried your code and it seemed to work, but honestly I am skeptical…

1.) I thought I read that the dimensions of a GIF can be compromised and thus render your suggestion unreliable.

2.) I have been struggling with this whole “How to securely Upload Images using PHP” like you cannot believe.

There is so much bad information out there, it is scary.

Every time someone tells me “Plan A” is the best way to do things, I find out it is not. So I’m feeling rather pessimistic after beating my head against a wall for the last 2 days.

Is there another way to check ALL FILE TYPES and determine that way whether a File is an Image File, and then use getImageSize() to determine What Kind of Image it is?

I just don’t want my code crashing is someone tries to upload “test.php.jpg”…

Thanks, and sorry if you didn’t get my earlier messages.

Debbie

It’s not so hard, really. What you need is to get the mime type of the uploaded file before you start working on it.
Look at the fileinfo functions here:
http://us3.php.net/manual/en/function.finfo-file.php

Example:

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, ‘/path/to/uploads/some_image.gif’);

Then test the $mime
something like this:
if(0 === strncmp($mime, ‘image’, 5)){
// process it
} else {
// delete it, ban the user who uploaded it
}

As per numerous people online and the PHP Manual, fileinfo() is not reliable.

Debbie

Did you mean to reply?

You are too concerned about this. Remember, when you allow the uploads of images you don’t want to just copy uploaded images as-is anyway. You usually want to resize the image and often make a thumbnail. So if the uploaded file is not an image the resizing will fail.

Also fileinfo is a good first step in testing that upload was actually an image.

One more thought: once image is uploaded and you use getimagesize and fileinfo to ‘pre-validate’ it, you then can move it to a pre-defined directory like /uploaded_images/
and in your httpd.conf you can add this line for your images directory
<Location /uploaded_images>
RemoveHandler application/x-httpd-php
</Location>

If you need it to be absolutely clean, the safest thing to do is to recreate the image using GD.

http://php.net/manual/en/book.image.php

ultra1 may only have a handful of posts, but they seem to be a pretty good start. =p

As he said, you first want to check the mime-type. Yes, mime-types can be spoofed… so can everything else. However, it usually isn’t.

Also, as dk said, you don’t generally want to worry about the extension so much. If a file is a PHP file and I expect it to be a PHP file, I want to run it. If I don’t expect it to be a PHP file and it is, I want to avoid running it. The way to fix that is make sure your image is what it is.

wonshikee’s approach is the most secure. You can’t really recreate an image that isn’t an image. However, that takes a lot of processing power. If you hope for this to be a high volume site, I wouldn’t use that approach.

The last solution offered by ultra1 is the approach I would choose. I don’t randomly dump upload files any old place in my system (especially not user uploaded files). I put them in one confined location. Since it is one confined location, I can very easily make it so PHP can’t be run from that location (using the bit of code that he provided).

No offense, but I do feel that you are worrying about all of these crazy edge cases without worrying about the bigger picture and the more common hacking approaches or shooting yourself in the foot by dooming your site to poor performance. For example, why don’t you just change the filename of the uploaded file? Why leave it with the filename that they gave? Why not give it some randomly generated file name which uses the extension you expect it to have? If you do that simple thing, even if they do upload hack.php.jpg, when you go to where the file was uploaded you’ll just get a wall of the hackers text or a browser error. Simple, quick and efficient fix to solve the problem. =p