18

I have an image upload php website. Users can upload images to my website. A user claims he can hack my website using an uploaded image.

I opened all the images that he uploaded to my server with notepad. The last line of one image is:

Àpa@ ;
<?php

echo "test ok";
?>

Can he hack my website using this image? How do I prevent users from uploading images like this?

3
  • Please tell us what check you already perform on the file. Do you check the extension at least? Some answers make assumptions on that.
    – Aki
    Mar 21, 2013 at 12:22
  • extennsion is .gif Mar 21, 2013 at 12:44
  • How do you display the image? The extension .gif at least reduces the possibility of code execution. If you use require() and not standard HTML then it's dangerous, else David Mah is right.
    – Aki
    Mar 21, 2013 at 13:21

3 Answers 3

14

Image uploads (any files in general) are very hard to make completely secure - especially in PHP, which provides many attack vectors.

If you, for example display the image by calling

require($someImage);

and that image has PHP code inside (like the one you posted), it may be interpreted and executed as such.

My guess is, if he claims he's owned your site, he most probably has. The image you've provided in itself won't do anything except print "test ok", but that code could easily be exchanged for some that gives unauthorized (even completely unrestricted) access to your site and server.

To make sure the file uploaded to your site is in fact an image, re-process it using GD (or Imagick), and save the processed image. It's bad practice to save the original image, especially using the original file name, as this opens up for many other attacks (for example directory traversal and file overwriting).

More information: https://www.owasp.org/index.php/Unrestricted_File_Upload

2
  • 1
    +1. This seems to me to be the most likely attack vector in this case. If you have another page that does an include() or require() where the filename can be manipulated by the caller, all he has to do is work out how to call that. If your site displays PHP error messages, they may have given him clues as to how to proceed with this.
    – SDC
    Mar 22, 2013 at 13:34
  • How many times does a developer call require($someImage);?.
    – magallanes
    Oct 21, 2018 at 12:54
21

Yes, your server could run PHP code within an image file if it is not configured correctly:

http://www.phpclasses.org/blog/post/67-PHP-security-exploit-with-GIF-images.html

An example from that is image.gif.php. A file can be be both a valid image and a valid PHP script, it's not sufficient to simply check image size or other properties. Nor is it sufficient to strip metadata, an uncompressed GIF can contain PHP as image data (though it may be unpretty), PNG supports arbitrary data chunks.

The flaw is accepting uploads with insufficient sanity checking, specifically attempting to prevent unwanted filenames (e.g .php) by using a non-anchored regex like \.(png|gif|jpg|jpeg) (no $ anchor), and allowing those images to be served from a directory with PHP processing enabled. Best practise is that you should probably never use a user provided filename as-is.

These are fairly classic data validation and input validation failures.

If you follow the PHP installation instructions (for Apache 2) you'll have something like this in your Apache config:

<FilesMatch "\.ph(p[2-6]?|tml)$">
    SetHandler application/x-httpd-php
</FilesMatch>

Note the $ anchor, it will prevent file.php.gif from being interpreted by PHP. (What's missing from those instructions is making sure that PHP is limited by a <Directory> context containing only trusted code, and not writeable by the web server user.)

If you don't follow those instructions, and use mod_mime's AddType (or AddHandler) instead:

AddType application/x-httpd-php .php      # STOP! 

This can cause the same problem because mod_mime may do something you don't expect with multiple extensions. See http://blog.dynom.nl/archives/Be-careful-with-double-extensions_20081024_25.html (thanks to Hendrik Brummermann for pointing this out). This risk can be mitigated with correctly configured <Directory> context to allow only trusted code.

This document (PDF) is a little old, but it covers the mitigations well: http://www.net-security.org/dl/articles/php-file-upload.pdf

Another possible source of problems is insecure include/require statements (also covered in that PDF) which allow an attacker to include uploaded content by altering query strings or HTTP request headers.

See also the recent related question: Risks of a PHP image upload form (though I do not think it is correct to rely on getimagesize to verify images), and Use PHP to check uploaded image file for malware? (which contains a useful set of links).

6
  • extension of file is .gif. I am using this method if(end(explode(".",'gif')) == "gif"){ upload_file(); } Mar 21, 2013 at 9:16
  • 2
    I'd have voted this answer up if mr.spuratic hadn't suggested that applying a regex to the filename/extension in anyway validates the content or mimetype (even with an end anchor). Yes that's a fairly obvious attack vector - it's not a valid defence strategy. (Potentially hostile) Uploaded content should be stored completely outside the doc root and in the case of files, preferably converted to a different format using lossless compression. How you handle meta-data is a complex question - this is where PHP malware resides - but it may also contain copyright info.
    – symcbean
    Mar 21, 2013 at 9:40
  • My intent was to point out how it was being done incorrectly thus creating the vulnerability, updated and clarified the point I hope. Mar 21, 2013 at 9:53
  • 3
    Please note Apache's support for double extensions: something.php.gif will be handled by PHP in common installations despite the final extension being .gif. Mar 21, 2013 at 10:52
  • Good point, incorporated this and your link, thanks! Mar 21, 2013 at 11:54
1

I'm going to assume that you're running LAMP (and an answer for other php setups would be very similar).


Most likely, his code cannot do anything to your site.

Let's say that Apache is serving files out of /var/www on your server. Say somebody visits index.php on your website.

  1. Apache will receive that they are looking for /index.php
  2. Apache will look for the file /var/www/index.php
  3. If Apache is running mod_php, then it will check if index.php matches a rule in the mod_php configuration file in some way. Your mod_php config file (probably at /etc/apache2/mods-available/php5.conf) is most likely a superset of this minimal example I've created below:

    <IfModule mod_php5.c>
        <FilesMatch ".+\.ph(p[345]?|t|tml)$">
            SetHandler application/x-httpd-php
        </FilesMatch>
    </IfModule>
    
    • If the file name does match, then Apache will run the file through a php interpreter, creating a web page that it will serve that to the user.
    • If the file name does not match, then Apache will just serve that to the user.
    • (These details skip many bits of apache that I don't think are relevant here)

Let's say that a user uploads an image, say evil_image.png, and it has arbitrary PHP code in it.

Let's also say that you serve it to users from somewhere, say at /images/evil_image.png (so within your filesystem, /var/www/images/evil_image.png).

When somebody tries to retrieve this image by accessing your website at /images/evil_image.png, Apache will run through the steps that I outlined above. At step 3, /images/evil_image.png will not match the pattern from your configuration file, so you will not execute the code as php. You will simply serve the image to the user.

The user will receive the image file that has the malicious crafted text stored inside of it. What is important is that your server has not tried to execute the code, rendering it ineffective.


I am not saying that it is impossible for that code to be executed. I will tell you that you need to sorely miss configure your web server in order to cause that code to be executed.

2
  • 1
    is there any chance to execute JavaScript in that file. I mean if the attacker add text like this <script>alert(''); </script> Mar 21, 2013 at 8:54
  • @messifan Probably best to add this to your original question but the answer is "Yes, if he can find an HTML injection flaw in your website."
    – Ladadadada
    Mar 21, 2013 at 10:16

Not the answer you're looking for? Browse other questions tagged .