How can I protect a PHP image upload script from e

2019-02-09 16:57发布

问题:

I've created (using a script and some help from Stack and some help from friends; I know very little about PHP) a simple page for a local non-profit publication where people can upload photos.

I'm not great with security (from a basis of ignorance, not deliberate negligence) but I've taken the following steps to protect this page:

• the PHP script is set to only accept .jpg, .png and .tif files for upload;
• the subfolder that it saves the form content to has permissions set at 700, and the subfolder it saves uploaded photos to has permissions set at 700;
• according to documentation, my host has the following configuration to ensure that only .php files run as .php:

<FilesMatch \.php$>
    SetHandler php52-fcgi
</FilesMatch>

• I’ve put an .htaccess file in the relevant (main and saved content) folders:

RemoveHandler .php
RemoveHandler .inc
RemoveHandler .pl
RemoveHandler .cgi
RemoveHandler .py
RemoveHandler .fcgi

Overnight, however, somebody found this test page and submitted what seems to be a perfectly benign test message and small .jpg. This is a private test page with a non-intuitive URL that only I and about three other people know about; none of the others sent this test.

This obviously has me worried that there's something hinky going on, and I'm worried that I don't know enough about security to make sure this page is safe.

Is there something obvious that I'm missing?

回答1:

When dealing with uploaded you should keep in mind that all the data you can find in the $_FILES array can be faked. It's traveling through HTTP so it's pretty easy to give the image/jpg mime to an executable file for exemple.

1- Check the true mime

PHP come with some function to check the real mime of a file. For that you should use fileinfo

$finfo = new finfo(FILEINFO_MIME, "/usr/share/misc/magic");
$filename = "/var/tmp/afile.jpg";
echo $finfo->file($filename);

2- Check the image's properties

You apparently want to upload only image , so the received file must have a width and a height :

Use getImageSize() to get all the required information about the image. If it return false , the file is probably not an image and you can delete it. getImageSize can also give you a mime type , but i don't know if it can be trusted.

2.5- Reprocess image

As suggested by user628405 , reprocessing the image with GD is probably the more secure thing to do.

$img = imagecreatefrompng('vulnerable.png'); 
imagepng($img, 'safe.png');

Obviously it has to be adapted according to the image type. See all the imagecreatefrom* in php documentation.

3- Upload folder In addition of what you have already done :

Make sure your upload folder is not available from the web. Validate the uploaded file then move it to an other folder if needed and rename the file. It will prevent hacker from executing a malicious file (can't execute it if it can't be reached by an url).

Further reading : https://www.owasp.org/index.php/Unrestricted_File_Upload



回答2:

Don't rely on any data from the client, including content type!

Don't save uploaded files in the web root. Uploaded files should be only accessible via your scripts, for better control.

Don't save uploaded files with their original file names and extensions! Store this data in a database for retrieval later.



回答3:

You can check the MIME type of the file, but don't worry as long as your php handler can only execute .php files and you're taking care of not saving uploaded .php files in your script, you're not exposing any security leak.

This is valid for .php files as well as any other server-side scripting language installed on your server of course.

A better idea is to keep a white of the extensions you're accepting to save on your filesystem.



回答4:

I would ignore the MIME type and the file extension of the incoming file. These can be faked.

Store those files in a directory if you are going down that avenue.

Ensure that that directory is just for images (music) and then get a script to place the correct extension on them by looking at the files format.

Also ensure that that directory cannot execute PHP (or anything else).

This will keep you safe.



标签: php security