Insecure file upload - PHP

Insecure file upload - PHP

Need

Secure file upload process

Context

  • Usage of PHP 7.0 for server-side scripting and web development
  • Usage of Request for making HTTP requests

Description

Non compliant code

        public function uploadFile(Request $request)
{
    if($request->hasFile('file')) {
        $file = $request->file('file');
        $filename = $file->getClientOriginalName();
        $destinationPath = 'uploads';
        $file->move($destinationPath,$filename);
        return back()->with('success','File Upload successfully');
    }
}
        
        

The above PHP function is used to upload a file in a Laravel application. It takes a file from a request and moves it to the 'uploads' directory with its original name.

Here are the vulnerabilities in the above code:

1. No file extension validation: The function does not check the file's extension. This means that users can upload files with any extension, including .html, .php, .exe, etc. These files could potentially contain malicious code that can be executed on the server or on the client's browser.

2. No check for double extensions: The function does not check for files with double extensions, like .php.jpg. These files can be used to bypass some security checks that only look at the last extension.

3. No check for malicious code: The function does not validate whether the file is free from malicious code. This means that if the file contains any malicious code, it will be uploaded and stored on the server.

4. Using the original file name: The function uses the original name of the file. This can lead to various security issues, such as directory traversal attacks or overwriting important server files if the filename is manipulated.

5. No file size limit: The function does not limit the size of the uploaded file. This can lead to Denial of Service (DoS) attacks where the server's storage is filled up with large files.

Steps

  • Validate the file extension: Only allow safe file extensions. For example, if it's an image uploader, only allow .jpg, .png, etc. Do not allow .php, .html, .exe or any other potentially dangerous file types.
  • Check for double extensions: Some attackers may try to upload files with double extensions like .jpg.php. Make sure to validate against this.
  • Scan the file for malware: Use a server-side solution to scan uploaded files for malware or other potentially harmful content.
  • Limit the file size: This can prevent DoS attacks where an attacker tries to fill up your server's disk space.
  • Rename the file upon upload: This can prevent an attacker from being able to predict the file path and access it directly.
  • Store the files outside of the webroot: This way, even if an attacker manages to upload a malicious file, they won't be able to execute it.
  • Use a whitelist approach for file validation: Instead of trying to block bad files, only allow known good types.
  • Implement a Content Security Policy (CSP): This can prevent a wide range of attacks, including Cross Site Scripting (XSS) and other code injection attacks.

Compliant code

        public function uploadFile(Request $request)
{
    if($request->hasFile('file')) {
        $file = $request->file('file');
        $filename = $file->getClientOriginalName();
        $extension = $file->getClientOriginalExtension();

        // Validate file extension
        $allowedExtensions = ['jpg', 'png', 'doc', 'pdf']; // Add your allowed extensions here
        if(!in_array($extension, $allowedExtensions)) {
            return back()->with('error', 'Invalid file type.');
        }

        // Check for double extensions
        if(strpos($filename, '.') !== strrpos($filename, '.')) {
            return back()->with('error', 'Double extensions are not allowed.');
        }

        // Rename the file upon upload
        $filename = time() . '.' . $extension;

        // Move the file to a secure location
        $destinationPath = storage_path('uploads'); // Make sure this directory is outside of the webroot
        $file->move($destinationPath, $filename);

        return back()->with('success','File Upload successfully');
    }
}
        
        

The updated code includes several security measures to prevent insecure file uploads:

1. File Extension Validation: The code checks the file extension against a list of allowed extensions. If the file extension is not in the list, the upload is rejected.

2. Double Extension Check: The code checks if the file name contains more than one dot, which could indicate a double extension. If a double extension is detected, the upload is rejected.

3. File Renaming: The code renames the file upon upload using the current timestamp and the original file extension. This prevents attackers from predicting the file path.

4. Secure File Storage: The file is moved to a secure location outside of the webroot. This prevents attackers from executing any malicious files they might manage to upload.

Note: This code does not include malware scanning or a Content Security Policy (CSP). These features should be implemented server-side and are beyond the scope of this code snippet.

References