Securing File Uploads
Allowing users to upload files introduces risk. Attackers may try to upload scripts or malware. Use a layered approach: validate file types, store uploads outside the web root, and generate unique names.
Validating file types
Check the MIME type reported by PHP and use finfo to verify the file contents. Limit uploads to specific extensions:
<?php
declare(strict_types=1);
$allowed = ['image/jpeg','image/png'];
$finfo = new finfo(FILEINFO_MIME_TYPE);
$type = $finfo->file($_FILES['upload']['tmp_name']);
if (!in_array($type, $allowed, true)) {
die('Invalid file type');
}
?>
Storing securely
Place uploaded files in a directory outside of your document root. Store only references in the database. Generate random filenames to prevent guessing:
<?php
declare(strict_types=1);
$targetDir = dirname(__DIR__, 2) . '/uploads';
if (!is_dir($targetDir)) {
mkdir($targetDir, 0755, true);
}
$newName = bin2hex(random_bytes(16)) . '.' . pathinfo($_FILES['upload']['name'], PATHINFO_EXTENSION);
move_uploaded_file($_FILES['upload']['tmp_name'], $targetDir . '/' . $newName);
?>
When serving files, use a PHP script that reads the file from the secure directory and sets appropriate headers. Never allow the web server to serve user uploads directly.