Apologies if this is answered elsewhere. I was not able to find a similar post.
I need some expert advice on security issues with uploaded images in a PHP application.
Briefly, I have a web app that displays uploaded images as a slideshow. The images are uploaded by the user through a custom-built CMS (which is on the same domain as the public pages) and records are sent to a database that include the filename as it was on the user’s computer. Everything is working okay, however I decided to put the upload directory for the images outside or above the webroot, so e.g.
domain name points to public_html,
host/public_html/index.html is home page,
host/uploads/ is where the upload folder is
The images are now accessed in something like the following manner from the slidehsow page:
<?php
$query = “SELECT filename,imgID FROM pics”;
$result = mysqli_query($dbconnect,$query);
while($record = mysqli_fetch_array($result)) {
echo ‘<div class=“slide”><img src="fetch_image.php?file=’ . $record[‘filename’] .‘" id="slide_’ . $record[‘imgID’] . ‘" /></div>’;
}
?>
fetch_image.php looks something like:
<?php # fetch_image.php
if(isset($_GET[‘file’])) {
// Access the root directory
$root_dir = dirname(dirname(dirname(FILE)));
$file = $root_dir. ‘/uploads/’ . $_GET[‘file’];
$size = getimagesize($file);
if (file_exists($file) && $size) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
}
The divs with class ‘slide’ in the generated HTML have absolute positioning and display:none so all will stack up on top of each other and are hidden when the page loads. A javascript file controls the slideshow by showing and hiding instances of ‘slide’ according to thumbnail links clicked by the user.
This works a treat, however, and I’m coming to the point, considering that in the Content Management System the file upload script creates a copy of the uploaded file using imagecreatefromjpeg() and imagecopyresampled(), is this layer of security unecessary? In other words would it be safe to use relative links (e.g. /images/thefile.jpg) here and move the upload directory inside the webroot? There doesn’t seem to be a lag in performance as it is, but if there were 20 images that would be 40 page requests (there is a row of thumbnail images), does that make a significant difference to demands on resources and speed? I don’t know if having upload dir above webroot makes any difference at all in this situation.
BTW the upload script is part of a freely available file upload kit and I’m not sure if it’s permitted to place any lifted code from it here. It’s the jquery fileuploader.
I have been googling this subject for the past two days and am really surprised that such a common application of PHP is not better documented.
Any ideas on the subject would be most welcome.