Arka Roy

Enhance File Upload Security with PHP

Allowing user to be able to upload a file is a very common functionality that developers need to implement. But how can we make sure that user would not upload anything malicious?

We often face a situation where we need to provide our users a way to upload image, pdf, document etc. The basic html form for file upload is able to handle this with the help of PHP. The basic process of uploading user submitted files to the server with PHP is fairly easy and simple. But there should be some security measures. What will happen if a "not good" user uploads a malicious file to our server?

Here we will discuss some of this security measures to block the holes.

The Form

Before anything else, lets assume we have a form for the users to upload a file.

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data">
    <label for="file">Select File:</label>
    <input type="file" name="file" id="file">
    <input type="submit" name="upload" value="Upload File">
</form>

Remember to use method="post" whenever using a form for file upload. As you are already aware of, enctype="multipart/form-data" is necessary because it tells the browser how to handle the data submitted as a file.

$_FILES Array

As soon as the file uploads, its details become available in the PHP's $_FILES superglobal array.

If you add the following php lines at the top of your page,

<?php

if(isset($_POST['upload'])) { // Checking whether the form has been submitted
    echo '<pre>';   
    print_r($_FILES);
    echo '</pre>';
}

and then you upload a file named flower.jpg. After you click 'Upload File' button, the details would be shown like this:

Array
(
    [file] => Array
    (
        [name] => flower.jpg
        [type] => image/jpeg
        [tmp_name] => C:\xampp\tmp\php9F19.tmp
        [error] => 0
        [size] => 780831
    )

)

The Errors

Before we continue, lets take a look at the errors we can have. In the previous example, the error is 0 which means that there is no error and the file has been successfully uploaded.

Lets take a look at the various error codes and what they mean.

0 => No Error
1 => Exceeds upload_max_filesize in PHP configuration
2 => Exceeds MAX_FILE_SIZE in hidden form field
3 => File partially uploaded
4 => No file to upload
6 => No temporary upload folder defined
7 => PHP failed to write to disk
8 => A PHP extension prevent the file to be uploaded

MAX_FILE_SIZE

In some cases, you might want to limit the size of the file to be uploaded. The MAX_FILE_SIZE field tells the browser to prevent the upload if it exceeds certain size. To use this feature, add the following code before the file input field.

<?php
    $max_size = 100 * 1024; // 100KB
?>
<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $max_size; ?>">

If a file larger than the size set, the error will be set to 2 and it will not be attempted to upload.

Upload Directory

When setting or specifying a directory to store the uploaded files, it is much professional to consider some points before doing so.

The directory where the uploaded file will live, must be set writable. In Linux, permission to the folder must be set to at least 755 or 775.

If the files are going to be accessible by public, the directory can be under the root of the server. But if the files are protected or contains sensitive data, then it is much wiser to put the directory outside the scope of the server root so that it cannot be accessible via public url.

Move Uploaded File

It is necessary to move the uploaded file to the directory specified for the files. Otherwise, the uploaded file will be lost as it is just saved as a temporary file at first.

To move the uploaded file, we will use move_uploaded_file() method:

<?php

if(isset($_POST['upload'])) { // Checking whether the form has been submitted
    // ...
    $directory = __DIR__ . '/uploads/';
    if($_FILES['file']['error'] == 0) { // No error
        $result = move_uploaded_file($_FILES['file']['tmp_name'], $directory . $_FILES['file']['name']);
        if($result) {
            echo $_FILES['file']['name'] . ' has been successfully uploaded.';
        } else {
            echo 'There was a problem uploading ' . $_FILES['file']['name'];
        }
    }
    // ...
}

Now the uploaded files will the saved in the 'uploads' directory.

We have improved to some extent but there is a long path to go. We have not implemented any check on file types, file names and we have not provided any support for uploading multiple files. Also, if the uploaded files have same filename, the older one will be overwritten.

To avoid these situations and implement more validation, we will handle the upload a bit differently. We will Create a File Upload Class in PHP to handle the file upload more efficiently.

Other Articles

Create Drop Cap Letters in CSS

In this tutorial we will use CSS3 to create Drop Cap, a traditional newspaper technique of making the first letter of a paragraph capital and take the height of three or four lines. In that way, it is easier to grab the attention of the reader and specify the start of a section.

Create File Upload Class in PHP

File upload is a very common functionality that almost all applications have. But we need to make sure that the system is smart enough to prevent malicious usage of this functionality. How can we achieve that?