I usually do not write in this blog about general PHP issues unless it is somehow related with the PHPClasses site.
However, this time I feel that I should use the fact that new blog posts here gets great exposure, as they are notified by e-mail to over 220,000 PHP developers. So I am writing this because it is very important to spread the word about this PHP security exploits that can used to abuse from sites written by many developers that are not well aware of security issues.
Despite in the PHPClasses site there is a great concern about security, I am not really a security expert. More than anything, I am just passing the word.
- The PHP GIF security issue
The problem that was discovered is that you can insert PHP code in the middle of a GIF image. That would not be a problem if it was not for the insecure ways some developers use to serve images upload by their users.
Usually, uploaded files are moved to a given directory. If the site then serves the images directly from that directory and preserve the original file name, the site may be open for security exploits.
For instance, lets say the attacker uploads an image named image.gif.php . The image may be moved to the images directory. If the the Web server is configured as usual to process requests with files .php extension, and the site serves the image with the following URL, the request will execute the PHP code inside the image.
http://www.yoursite.com/images/image.gif.php
- Avoiding the problem
The basic solution to avoid this problem is to either serve images only with actual extensions of image files (.gif, .png, .jpeg), or protect the upload directory to avoid direct requests to where the images are located.
Depending on your PHP setup, it may or may not be easy to protect your uploaded images directory. In Apache it can be done using a .htaccess file with lines like this:
<Files images>
deny from all
</Files>
Alternatively you can use other PHP functions to serve image files as images, and so, avoid triggering the execution of PHP scripts embedded in image files like these readfile.
http://www.php.net/readfile
$file = 'image.gif.php';
Header('Content-Type: image/gif');
readfile('images/'.basename($file));
Note the use of basename function to avoid injection of malicious paths. This way, only files from inside the images directory will be served, even if the original file named was forged to steal server sensitive files like /etc/passwd .
- Other things you should not do
Usually the getimagesize function is used to verify whether the uploaded file is a valid image.
In this case it would not work because the image can still be valid and have a sequence of bytes that can be interpreted as PHP. It is not wrong to use the getimagesize function. Just be aware that it does not avoid the problem.
Another thing that I have seen people doing is to use the include or require functions to serve images stored on the server this. Obviously, this will trigger the execution of PHP code embedded in the image file.
Checking the file name extension before accepting the upload files would not avoid the security hole opened by using include or require to serve the image file on the server side directory. Always use readfile or equivalent to serve the images.