I am working on script to a upload image files Securely. can anyone please review my code and suggest improvements on security.
<input type="file" name="images[]" id="image" multiple="multiple">
check if request method is POST and request was made from same domain and form was submitted with submit btn
if (is_post_request() && is_request_same_domain() && isset($_POST['add-list-submit'])) {
Convert the $_FILES array to a cleaner version
$images = rearrange_files_array($_FILES['images']);
function rearrange_files_array($file)
{
$file_array = [];
$file_count = count($file['name']);
$file_keys = array_keys($file);
for ($i = 0; $i < $file_count; $i++) {
foreach ($file_keys as $key) {
$file_array[$i][$key] = $file[$key][$i];
}
}
return $file_array;
}
Loop through the images
foreach ($images as $image) {
Check if image was upload, image mime type, extension, and size
if (!isset($image) || $image['error'] !== UPLOAD_ERR_OK) {
$errors['form'] = 'Please upload the images.';
} else {
if (!is_file_valid_image($image) || !has_valid_file_extension($image, ['jpeg', 'png', 'jpg'])) {
$errors['form'] = 'Only PNG and JPG file formats are allowed.';
}
if (has_max_file_size($image)) {
$errors['form'] = 'Max file size is 2.5 MB.';
}
}
function has_valid_file_extension($file, $allowed_file_extensions)
{
$file_extension = pathinfo($file['name'], PATHINFO_EXTENSION);
return in_array($file_extension, $allowed_file_extensions);
}
function is_file_valid_image($file)
{
$imageTypes = [IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_SWF, IMAGETYPE_PSD, IMAGETYPE_BMP, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM, IMAGETYPE_JPC, IMAGETYPE_JP2, IMAGETYPE_JPX, IMAGETYPE_JB2, IMAGETYPE_SWC, IMAGETYPE_IFF, IMAGETYPE_WBMP, IMAGETYPE_XBM, IMAGETYPE_ICO];
$info = getimagesize($file['tmp_name']);
$width = $info[0];
$height = $info[1];
$type = $info[2];
$bits = $info['bits'];
$mime = $info['mime'];
if (!in_array($type, $imageTypes)) {
return false; // Invalid Image Type
} else if ($width <= 1 && $height <= 1) {
return false; // Invalid Image Size
} else if ($bits === 1) {
return false; // One Bit Image
} else if ($mime !== 'image/gif' || $mime !== 'image/jpg' || $mime !== 'image/jpeg' || $mime !== 'image/png') {
return false; // Invalid Image Type
} else {
return true;
}
}
function has_max_file_size($file)
{
return $file['size'] > 2500000; // 2.5 MB
}
If there are no errors move the image to the uploads directory
$filename = bin2hex(random_bytes(12));
$file_ext = pathinfo($image['name'])['extension'];
$upload_path = UPLOAD_DIRECTORY . '/' . $filename . '.' . $file_ext;
move_uploaded_file($image['tmp_name'], $upload_path);
} else if ($width <= 1 && $height <= 1) {
. Obviously an image cannot be less than 1x1 px but then why do you care since an image size of at least 2x2 px will pass your test ? This test is not useful. \$\endgroup\$