I develop a php script to replace a current one, that will have a lot of exposure to various markets/countries. This script between others offers an photo upload functionality .
After a lot of reading about the issue, I followed the approach described below. I would deeply appreciate your comments on its security.
- The photo is uploaded in a private 777 folder outside web root.
- A check for white listed extensions is performed (allow only jpgs, gifs, pngs) everything else is deleted.
- Use of getimagesize to check of min-max dimensions and photo validity.
- Check of mimetype and file extension match.
- Resizing of uploaded photo to std dimensions (using imagecopyresampled).
- Saving the created files as jpg.
- Removal of original file.
- Save photos with a new (not random name) ie img51244.jpg.
- Move the new photos to variable subdirectories of a public folder (777 permissions) according to a non predictable algorithm. I.e.,
img10000.jpg
will be stored atphotos/a/f/0/img10000.jpg
whileimg10001.jpg
will be stored atphotos/0/9/3/img10001.jpg
. This is done for other reasons (use of subdomains for static content serve or use of a CDN).
The script will run on a linux dedicated server.
That's a quite complete approach, but I do not see any code execution prevention mechanism.
You should make sure that the content of the image is never included (with an include or require call) or executed through eval().
Otherwise, php code included at the end of the file could be executed.
You can also try to detect php code inside the image content (with file_get_contents, and then a regex searching for " < ? php " for instance ) but I could not find a 100% secure way to eliminate suspicious code without destroying some (valid)images.
You should also check uploaded file size, as getimagesize can sometimes exceed available RAM memory. It's also good to assume that your script can crash at any point (for example when the electricity go down), so you should implement some clean up procedures to remove left, unneeded files.
apache
(or whatever user your webserver runs at). I'm not sure why you wouldn't use php's default temporary directory here, since it tends to be outside of the web root too./.png/
actually matchesapng.php
.Steps 5 to 8 are not security-related.
Step 9: I'm assuming that your site allows everyone to see every photo. If that isn't the case, you should have a URL scheme with substantially longer URLs (say, the hashsum of the image).