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
}
}
?>