1

Possible Duplicate:
PHP image upload security check list

I'm setting up a file upload form on my website, where the user can upload an image. For security, I check the image size and mime type before renaming the file and storing it.

What I'm worried about is how to prevent a user from constantly uploading different files and abusing my server. Is there a way to prevent this? I was thinking of keeping track of the user's IP (via $_SERVER["REMOTE_ADDR"] and $_SERVER["HTTP_X_FORWARDED_FOR"]), with a timestamp for each upload and limitting uploads to X per hour. Any feedback or suggestions are appreciated.

Thanks

Community
  • 1
  • 1
user1193425
  • 269
  • 1
  • 4
  • 11
  • Is it something you can just password protect and use sessions? Then you can limit by user... – Paronity Dec 05 '12 at 19:34
  • 1
    you have user management on your site? so should be trivial to limit uploads per user (time\number\size) etc –  Dec 05 '12 at 19:34
  • Just in case you don't know, checking the browser supplied MIME type is useless, it can be manipulated freely – Pekka Dec 05 '12 at 19:38
  • It will be near impossible without requiring users to be logged in. A hacker could spoof their IP. Also, users within a private network usually send out requests using the same external network IP, so you'd be blocking a bunch of legitimate users. – Ruan Mendes Dec 05 '12 at 19:40
  • http://stackoverflow.com/questions/4166762/php-image-upload-security-check-list http://stackoverflow.com/questions/12617070/secure-image-upload-with-php http://stackoverflow.com/questions/7317083/php-image-upload-security-approach – Shahrokhian Dec 05 '12 at 20:03
  • I don't have any user management, and I'm trying to avoid having a user login. Also, I'm using getimagesize() as well as checking the mime types. Is there anything else I should be doing? – user1193425 Dec 05 '12 at 20:14
  • Nope, if you check the type with `getimagesize()` everything's fine – Pekka Dec 05 '12 at 21:06

1 Answers1

1

Indeed, someone pointed out above $_FILES[x]['type'] can be very easily and arbitrarily changed. Make sure you never rename anything .php or any other parsed/executed file such as .shtml ... One way to avoid this is to always, when you serve the image back out to users, to use a single php script to serve them back and to use something like readfile() so the contents are never interpreted. Also, if you are only accepting images, you could use something as simple as getimagesize() to help validate that it is a real image. But once again, be wared, make sure that user uploaded contents can never be executed, specificially by uploading, and then accessing that uploaded file via their web browser. I am just making a point, I could imagine someone could take enough time to make a valid JPEG file that while it would parse via getimagesize() might contain harmful code if executed as .php. It's a long shot, but you must be prepared for anything. :)

On the subject of other types of abuse, you could use simple filters such as each IP only gets X bytes or total uploads (or both) per hour/day. If they exceed that limit, then use a very reliable captcha system such as reCAPTCHA. That way you never miss a legitimate request and abuse should be at a bare minimum, while not forcing every single image upload to go through a captcha.

Additionally, remember do NOT take precedence of X-FORWARDED-FOR. I have actually seen code like this:

if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { 
  $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else { 
  $ip = $_SERVER['REMOTE_ADDR'];
}

This is extremely wrong. X-FORWARDED-FOR can be sent by a forwarding proxy server, if it feels like it. It can also be sent by absolutely anything and everything else to trick fools into thinking their IP is something that is actually not.

As long as you use REMOTE_ADDR in combination with HTTP_X_FORWARED_FOR (and never trust HTTP_X_FORWARDED_FOR, only use it for a secondary reference), .. the chances of actual IP spoofing is next to nothing.

A.B. Carroll
  • 2,404
  • 2
  • 17
  • 19