PHP remote upload security I need to upload images to a remote HTTP server from a local script. The image name format is {32-char MD5}.jpg. Server directory format is 6c/d3/6cd3556deb0da54bca060b4c39479839.jpg. So, for example, if I upload the image called 6cd3556deb0da54bca060b4c39479839.jpg, it should be available at https://example.com/6c/d3/6cd3556deb0da54bca060b4c39479839.jpg.

The local script basically does a HTTPS multipart/form-data POST request with the "file" and "password" fields to a remote server (https://example.com/up.php).

Remote server has a PHP script (up.php) which checks if the "password" is correct and then either allows file uploading or disallows it.

Is this script secure? What can go wrong?

This is the code I use on the server. It checks password against SHA-512 hash and then checks if the filename extension is ".jpg".

&lt;?php
// Upload Script
//
// You need to post "file" and "password", which is checked
// against using SHA-512

// Check if the password is correct
$password_hash = "128-characters long SHA-512 string here";
if (hash("sha512", $_POST["password"]) != $password_hash) {
    http_response_code(403);
    echo "403 Access Denied";
    exit(1);
}

if(!empty($_FILES["file"])) {
    // Check if the filename extension is ".jpg",
    // otherwise deny uploading
    $file_parts = pathinfo($_FILES["file"]["name"]);
    if ($file_parts["extension"] != "jpg") {
        http_response_code(500);
        echo "Incorrect File Extension";
        exit(1);
    }

    // Filename of the file being uploaded
    $filename = $_FILES["file"]["name"];

    // Build a directory path
    $tmp_a = mb_substr($filename, 0, 2); // First 2 chars of a filename
    $tmp_b = mb_substr($filename, 2, 2); // 3 to 4 chars of a filename
    $tmp_c = $filename;
    $directory = "$tmp_a/$tmp_b";
    // Full path to the file including the directory
    $full_path = "$directory/$filename";

    // If the directory doesn't exist, then create it
    if (!file_exists($directory)) {
        mkdir($directory, 0755, true);
    }

    // Upload the file
    if (move_uploaded_file($_FILES["file"]["tmp_name"], $full_path)) {
        echo "Success";
    } else {
        http_response_code(500);
        echo "Something went wrong";
        exit(1);
    }
}
Because you specifically ask about security:

For comparing hashes like SHA, you should use hash_equals().

If you are requiring the use of a password, you shouldn't use SHA-512. While it's certainly better than MD5, instead use bcrypt. Bcrypt is heavily recommended for password storage, especially long-term.
With bcrypt, instead of using hash() and hash_equals(), you would use password_hash() and password_verify().

Should new directories really have read and execute permissions for the group and other users? Likewise, I would check the permissions of the file itself.
I would personally have the files as 0600 and directories as 0700 unless other permissions are needed.

Checking the file extension is only helpful for preventing naive false uploads. On Linux and most UNIX-like operating systems, a file extension means very little (if anything). It could be any type of file with a JPEG extension, likewise anything could have a JPEG file extension.


I don't know about the rest of the code.