×
Premium WordPress plugins, PHP Scripts, Android ios games, and Apps. Download Nulled PHP Scripts, Codecanyon Scripts, App Source Code, WordPress Themes here And Many More.
PHP File Upload: Handling Images and Documents Safely

File Uploads Are a Favorite Attack Surface

Any feature that lets a user put a file on your server is a feature an attacker will try to exploit. A poorly validated upload form can let someone upload a PHP script disguised as a JPEG, then execute it directly — a full server compromise through what looked like an innocent profile-picture feature. Here is how to handle uploads without leaving that door open.

Never Trust the File Extension Alone

Checking that a filename ends in .jpg proves nothing — an attacker can rename any file. Verify the actual content of the file instead. For images, getimagesize() reads the file headers to confirm it is genuinely a valid image:

$imageInfo = getimagesize($_FILES['upload']['tmp_name']);
if ($imageInfo === false) {
    die('Uploaded file is not a valid image.');
}
$allowedTypes = [IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_WEBP];
if (!in_array($imageInfo[2], $allowedTypes)) {
    die('Unsupported image type.');
}

For non-image documents, checking the MIME type via PHP's finfo extension is the equivalent step — never rely on the Content-Type header sent by the browser, since that is also just user-supplied input and trivially spoofed.

Enforce Size Limits at Every Layer

Size limits need to be set in three places: upload_max_filesize and post_max_size in php.ini, and an explicit check in your application code. Relying on php.ini alone means a misconfigured server (or a future server migration) silently removes your protection.

Always Rename Uploaded Files

Never keep a user-supplied filename. Beyond the obvious collision risk (two users uploading "photo.jpg"), an attacker-controlled filename can be used for path traversal attacks (filenames like ../../config.php) or to overwrite existing files. Generate a random name instead:

$extension = pathinfo($_FILES['upload']['name'], PATHINFO_EXTENSION);
$safeName = bin2hex(random_bytes(16)) . '.' . $extension;
move_uploaded_file($_FILES['upload']['tmp_name'], $uploadDir . $safeName);

Store Sensitive Files Outside the Public Web Root

For anything that shouldn't be directly accessible by URL — invoices, ID documents, private contracts — store the file outside the publicly served directory entirely, and serve it through a PHP script that checks the requester actually has permission to view that specific file. Storing sensitive documents directly in a public uploads folder, reachable by anyone who guesses or finds the URL, is a common and serious mistake.

Disable Execution in Upload Directories

As a defense-in-depth measure, configure the web server (via .htaccess on Apache, for example) to prevent PHP files from executing inside the uploads directory at all. Even if a malicious file slips through validation, it cannot run.

Putting It Together

None of these steps is individually complicated, but skipping even one of them is how upload features become the entry point for a server compromise. This is one of the most common ways small business websites actually get hacked — not through some exotic exploit, but through a contact form or profile-picture uploader that never validated what it was actually receiving.

Not sure if your current site's upload forms are safe? We can audit it.