PHP Image Upload Checklist

I am programming a script to upload images to my application. Are there the following security measures to make the application safe from the side of the script?

  • Disable PHP startup inside the download folder using .httaccess.
  • Do not allow downloads if the file name contains the string "php".
  • Allow only extensions: jpg, jpeg, gif and png.
  • Allow only image file type.
  • Deny image with two file types.
  • Change the name of the image.
  • Download to a subdirectory, not to the root directory.

This is my script:

$filename=$_FILES['my_files']['name']; $filetype=$_FILES['my_files']['type']; $filename = strtolower($filename); $filetype = strtolower($filetype); //check if contain php and kill it $pos = strpos($filename,'php'); if(!($pos === false)) { die('error'); } //get the file ext $file_ext = strrchr($filename, '.'); //check if its allowed or not $whitelist = array(".jpg",".jpeg",".gif",".png"); if (!(in_array($file_ext, $whitelist))) { die('not allowed extension,please upload images only'); } //check upload type $pos = strpos($filetype,'image'); if($pos === false) { die('error 1'); } $imageinfo = getimagesize($_FILES['my_files']['tmp_name']); if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg'&& $imageinfo['mime'] != 'image/jpg'&& $imageinfo['mime'] != 'image/png') { die('error 2'); } //check double file type (image with comment) if(substr_count($filetype, '/')>1){ die('error 3') } // upload to upload direcory $uploaddir = 'upload/'.date("Ymd").'/' ; if (file_exists($uploaddir)) { } else { mkdir( $uploaddir, 0777); } //change the image name $uploadfile = $uploaddir . md5(basename($_FILES['my_files']['name'])).$file_ext; if (move_uploaded_file($_FILES['my_files']['tmp_name'], $uploadfile)) { echo "<img id=\"upload_id\" src=\"".$uploadfile."\"><br />"; } else { echo "error"; } 

Any new tips are welcome :)

+56
security php upload
Nov 12 2018-10-12
source share
11 answers

Re-process the image using GD (or Imagick) and save the processed image. Everyone else is just fun for hackers.

Edit: and, as stated in rr, use move_uploaded_file() for any upload.

Later editing: By the way, you want to be very strict in your download folder. These places are one of the dark corners where many exploits take place. This is valid for any type of download and any programming language / server. Check out https://www.owasp.org/index.php/Unrestricted_File_Upload

+30
Nov 12 '10 at 18:22
source share

To check the security of image files, I can think of 4 levels of securities. They will:

  • Level 1: check the extension (extension file ends)
  • Level 2: check the MIME type ($file_info = getimagesize($_FILES['image_file']; $file_mime = $file_info['mime'];)
  • Level 3: read the first 100 bytes and check if they have any bytes in the following range: ASCII 0-8, 12-31 (decimal).
  • Level 4: check the magic numbers in the header (first 10-20 bytes of the file). You can find a few bytes of file headers here: http://en.wikipedia.org/wiki/Magic_number_%28programming%29#Examples

Note. Downloading the entire image will be slow.

+11
Nov 12 2018-10-12
source share

XSS Warning

Another very important point. Do not download or download anything that can be interpreted as HTML in a browser.

Since the files are in your domain, the javascript contained in this HTML document will have access to all your cookies, allowing you to attack XSS.

Attack scenario:

  • The attacker uploads an HTML file with JS code that sends all cookies to his server.

  • An attacker sends a link to your users by mail, PM, or simply through an iframe on his or any other site.

The safest solution:

Make downloaded content available only in a subdomain or another domain. Therefore, cookies will not be available. This is also one of Google’s performance tips:

https://developers.google.com/speed/docs/best-practices/request#ServeFromCookielessDomain

+7
Feb 07 '13 at
source share

You might want to run "is_uploaded_file" at $ _FILES ['my_files'] ['tmp_name']. See http://php.net/manual/en/function.is-uploaded-file.php

+6
Nov 12 '10 at 16:30
source share

Create a new .htaccess file in the uploads directory and paste this code:

 php_flag engine 0 RemoveHandler .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml AddType application/x-httpd-php-source .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml 

Just remember to rename the files u upload + forget about checking types, contents, etc.

+6
Aug 04 '12 at 11:18
source share

I will repeat what I wrote in a related question.

You can determine the type of content using the Fileinfo functions (mime_content_type () in previous versions of PHP).

Excerpt from the PHP manual for the earlier Mimetype extension, which is now being replaced by Fileinfo:

The functions in this module try to guess the type of content and file encoding by searching for specific sequences of magic bytes at specific positions in the file. Although this is not a bullet proof approach to the heuristics used does a very good job.

getimagesize() may also work well, but most of the other checks you perform are nonsense. For example, why the php line is not specified in the file name. You are not going to include the image file in a PHP script, simply because its name contains a php string, are you?




When it comes to re-creating images, in most cases this will improve security ... as long as the library you are using is not vulnerable.

So, which PHP extension is best for safely re-creating the image? I checked the CVE website. I think the applicable trio are those extensions:

From a comparison, I think GD is best suited because it has the least amount of security issues and they are pretty old. Three of them are critical, but ImagMagick and Gmagick do not work better ... ImageMagick seems very buggy (at least when it comes to security), so I choose Gmagick as the second option.

+5
Feb 18 '14 at 17:10
source share

If security is very important, use the database to save the file name and the renamed file name, and here you can change the file extension to somthing as .myfile and make a php file to send the image with headers. php can be more secure and you can use it in the img tag as blow:

 <img src="send_img.php?id=555" alt=""> 

also check the file extension with EXIF ​​before downloading.

+2
Apr 23 '12 at 16:40
source share

The simplest answer allows users to safely upload files to PHP : Always save files outside the root of your document.

For example: if your document root is /home/example/public_html , save the files in /home/example/uploaded .

Keeping your files safe because your web server runs directly, there are several ways that you can still make them available to your visitors:

  • Create a separate virtual host to serve static content that never runs PHP, Perl scripts, etc.
  • Upload files to another server (for example, cheap VPS, Amazon S3, etc.).
  • Store them on the same server and use the PHP script requests for the proxy server to ensure that the file is read-only and not for the executable.

However, if you go with parameters 1 or 3 to this list, and you have a vulnerability to include a local file in your application, your file upload form may still be an attack vector .

+2
Oct 28 '15 at 17:43
source share

The best way to protect your site when a user uploads an image is to take the following steps:

  • check image extension
  • check the image size with this function "getimagesize ()"
  • after that you can use the function "file_get_contents ()"
  • In the end, you should insert file_Content into your database, I think the best way! What do you think?
+1
Feb 28 '16 at 15:42
source share

For an image file, you can also change the file resolution after renaming to make sure it never executes (rw-r - r -)

0
May 29 '12 at 15:59
source share

I use a php-upload-script that creates a new random 4-byte number for each uploaded file, then the XOR content of the file with these 4 bytes (repeating them as often as necessary), and finally attaches 4 bytes to the file before saving.

To download 4 bytes, you must again disconnect from the file, the contents will be processed again using XORed and the result will be sent to the client.

Thus, I can be sure that the files that I save on the server will not be executed or have any potential value for any application. In addition, I do not need an additional database for storing file names.

Here is the code I use for this:

Download:

  <?php $outputfilename = $_POST['filename']; $inputfile = $_FILES["myblob"]["tmp_name"]; $tempfilename="temp.tmp"; if( move_uploaded_file($inputfile, $tempfilename) ) { $XORstring = random_bytes(4); $tempfile=fopen($tempfilename, "r"); $outputfile=fopen($outputfilename, "w+"); flock($outputfilename, LOCK_EX); fwrite($outputfilename, $XORbytes1); while ( $buffer = fread($tempfile, 4) ) { $buffer = $buffer ^ $XORstring; fwrite($outputfilename, $buffer); } flock($outputfilename, LOCK_UN); fclose($tempfile); fclose($outputfile); unlink($tempfilename); } exit(0); ?> 

Download:

  <?php $inputfilename = $_POST['filename']; $tempfilename = "temp.tmp"; $inputfile=fopen($inputfilename, "r"); $tempfile=fopen($tempfilename, "w+"); flock($tempfile, LOCK_EX); $XORstring = fread($inputfile, 4); while ( $buffer = fread($inputfile, 4) ) { $buffer = $buffer ^ $XORstring; fwrite($tempfile, $buffer); } flock($tempfile, LOCK_UN); fclose($inputfile); fclose($tempfile); readfile($tempfile); unlink($tempfile); exit(0); ?> 
0
Jul 17 '17 at 8:15
source share



All Articles