Dangerous File Upload

ID

php.dangerous_file_upload

Severity

critical

Resource

Path Resolution

Language

Php

Tags

CWE:434, NIST.SP.800-53, OWASP:2021:A4, OWASP:2021:A5, PCI-DSS:6.5.8

Description

Insufficient validations and/or restrictions against the content uploaded and/or where the uploaded content is stored

Rationale

Allowing file uploads without proper restrictions can lead to serious security risks.

If an attacker can control where a file is stored, they might overwrite configuration or sensitive files, depending on the web server’s permissions. Even partial control, like setting the file extension to .php, can enable indirect code injection attacks if the file is executed.

If uploaded files are used in web content, attackers can embed stored cross-site scripting attacks. This may also facilitate denial-of-service attacks or automatic execution of malicious files by vulnerable virus scanners.

Consider the following PHP example, where a user-supplied string is evaluated directly:

<?php
  $uploaded = $_FILES['uploaded'];
  $tmpFile = $uploaded['tmp_name'];
  $tmpFile = $_FILES['uploaded']['tmp_name'];
  $targetFile = UPLOAD_DIR . basename($uploaded['name']);

  if(move_uploaded_file($tmpFile, $targetFile)) { // FLAW
    // Do something
  }
?>

In this problematic example, none checks are performed against the uploaded file. At least we should be checking its path, size and content-type.

Remediation

The rewritten example of safer PHP code would look like this:

<?php
$fileData = $_FILES['uploaded'];
$tempFile = $fileData['tmp_name'];
$destinationFile = UPLOAD_DIR . md5(uniqid() . $fileData['name']);
$fileSize = $fileData['size'];

$fileInfo = finfo_open(FILEINFO_MIME_TYPE);
$fileType = finfo_file($fileInfo, $tempFile);

if (in_array($fileType, $allowedTypes) && $fileSize < MAX_UPLOAD_SIZE) {
    if (!$image = imagecreatefromgif($tempFile)) {
        trigger_error('Not a valid GIF image', E_USER_WARNING);
    }
    $imageInfo = getimagesize($tempFile);
    $fileType = $imageInfo['mime'];

    if (move_uploaded_file($tempFile, $destinationFile)) {
        // Handle successful upload
    }
}
?>

References