Skip to main content

Inappropriate coding practices - invalid file

Need

Enforce proper file validation and extension matching

Context

  • Usage of PHP 7.0+ for server-side scripting and web development
  • Usage of Request for making HTTP requests in Node.js

Description

Non compliant code

public function uploadFile(Request $request)
{
if($request->hasFile('file')){
$file = $request->file('file');
$filename = $file->getClientOriginalName();
$file->move(public_path().'/uploads/', $filename);
}
return back();
}

In the above code snippet, we have a function uploadFile in a Laravel controller that handles file uploads from a HTTP request. The function checks if the request has a file, gets the file, retrieves the original filename, and then moves the file to the 'uploads' directory in the public path.

However, this code is vulnerable due to inappropriate coding practices. Specifically, it does not validate or sanitize the file before storing it in the repository. This means that a user could upload a file that is not compatible with its extension, leading to potential issues. For example, a user could upload a .php file disguised as a .jpg file, which could then be executed on the server, leading to potential security risks.

The code does not check the MIME type of the file or validate the file extension against the file content. This is a common vulnerability in file upload functionality, as it could allow an attacker to upload and execute malicious files. It's important to always validate and sanitize user input, including files, to protect against such vulnerabilities.

Steps

  • Validate the file type before uploading. This can be done by checking the MIME type of the file.
  • Implement a whitelist of acceptable file types. Only allow files of these types to be uploaded.
  • Sanitize the filename to prevent any potential code injection attacks. This can be done by removing any special characters or potentially harmful sequences of characters.
  • Store the files in a secure location that is not directly accessible from the web. This can help prevent unauthorized access to the files.
  • Implement a system to verify the integrity of the files. This can be done by generating and storing a hash of the file content when it is uploaded, and then comparing this hash whenever the file is accessed.

Compliant code

public function uploadFile(Request $request)
{
$this->validate($request, [
'file' => 'required|mimes:jpeg,png,jpg,gif,svg,txt,pdf,docx|max:2048',
]);

if($request->hasFile('file')){
$file = $request->file('file');
$filename = $this->sanitize($file->getClientOriginalName());
$hash = hash_file('sha256', $file);
$file->move(storage_path().'/uploads/', $filename);
// Store the hash somewhere for future verification
}
return back();
}

private function sanitize($filename) {
return preg_replace('/[^A-Za-z0-9_\\-\\.]/', '_', $filename);
}

The updated code includes several security improvements:

  1. File type validation: The validate method is used to ensure that the uploaded file is of an acceptable type. The mimes validation rule is used to specify a whitelist of acceptable MIME types. The max rule is used to limit the size of the uploaded file to 2048 kilobytes.

  2. Filename sanitization: A new sanitize method is used to remove any special characters or potentially harmful sequences of characters from the filename. This helps to prevent code injection attacks.

  3. Secure file storage: The move method is updated to store the files in a secure location that is not directly accessible from the web. The storage_path function is used to get the path to the storage directory, which is a secure location for storing files in a Laravel application.

  4. File integrity verification: A hash of the file content is generated using the hash_file function and the sha256 algorithm. This hash can be stored and used to verify the integrity of the file whenever it is accessed.

References