CVE-2023-0455: Unrestricted Upload of File with Dangerous Type (CWE-434)
value: Unrestricted Upload of File with Dangerous Type in GitHub repository unilogies/bumsys prior to v1.0.3-beta.
CWE description: The product allows the upload or transfer of dangerous file types that are automatically processed within its environment.
CVSS v3 base score: 8.8
Published: 2023-01-26T22:15Z
Repository: https://github.com/unilogies/bumsys
Language: PHP
Files changed: core/config.php, core/functions.php
Commit date: 2023-01-22 15:02:01 +0600
Commit message: Update Security

Diff: diff --git a/core/config.php b/core/config.php
index 7804f22..18aff37 100644
--- a/core/config.php
+++ b/core/config.php
@@ -48,25 +48,48 @@ define('DB_CONN', DIR_INCLUDE . 'db/db.php');
  * Note: Must be less then or euqal to PHP MAX_FILE_UPLOAD_SIZE and post_max_size
  */
 $_SETTINGS["MAX_UPLOAD_SIZE"] = 8;
 
 /**
- * Define allowed mime type.
+ * Define allowed extension and mime type.
  * 
  * Can be seen common mime type here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
  * or
  *  https://www.iana.org/assignments/media-types/media-types.xhtml
  * 
  */
+
 // Vaild image type for upload. must be in lower case
-$_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"] = array("jpeg", "jpg", "png");
+$_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"] = array(
+    "jpeg"  => array("image/jpeg"),
+    "jpg"   => array("image/jpeg"),
+    "png"   => array("image/png")
+);
 
 // Valid document type for upload. must be in lower case
-$_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"] = array("pdf", "msword", "vnd.openxmlformats-officedocument.wordprocessingml.document", "vnd.ms-excel", "vnd.openxmlformats-officedocument.spreadsheetml.sheet");
-
+$_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"] = array(
+    "pdf"   => array("application/pdf"),
+    "doc"   => array("application/msword"),
+    "docx"  => array("vnd.openxmlformats-officedocument.wordprocessingml.document"),
+    "xls"   => array("application/vnd.ms-excel"),
+    "xlsx"  => array("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
+);
 // Valid audio type for upload
-$_SETTINGS["VALID_AUDIO_TYPE_FOR_UPLOAD"] = array("mpeg", "ogg", "opus", "aac", "wav", "webm");
+$_SETTINGS["VALID_AUDIO_TYPE_FOR_UPLOAD"] = array(
+    "oga"   => array("audio/ogg"),
+    "opus"  => array("audio/opus"),
+    "wav"   => array("audio/wav"),
+    "weba"  => array("audio/webm")
+);
+
+// Valid video type for upload
+$_SETTINGS["VALID_VIDEO_TYPE_FOR_UPLOAD"] = array(
+    "mpeg"  => array("video/mpeg"),
+    "ogv"   => array("video/ogg"),
+    "webm"  => array("video/webm"),
+    "mp4"   => array("video/mp4")
+);
 
 // Page title variable. All page title will be included here
 $_SETTINGS["PAGE_TITLE"] = array();
 
 // Dynamic Menu variable.
diff --git a/core/functions.php b/core/functions.php
index bff1914..b4b2bd2 100644
--- a/core/functions.php
+++ b/core/functions.php
@@ -1462,11 +1462,12 @@ function save_deleted_date($table, $data) {
  * @param string    $fileInputName  The file upload input name
  * @param string    $type           Optional. type of upload file. Defalut is image.
  * @param string    $location       Optional. Where the uploaded file has stored. Default is db and return an blob string
  * 
  */
-function easyUpload( 
+
+ function easyUpload( 
     array $file, 
     string $location="db",
     string $newFileName="",
     string $type="image"
     ) {
@@ -1478,113 +1479,91 @@ function easyUpload(
         return "There is no file found to be uploaded.";
     }
 
     global $_SETTINGS;
 
-    $type = strtolower($type);
-    $extensionName = strtolower(explode("/", $file["type"])[1]);
+    $mimeType = strtolower($file["type"]);
+    $extension = explode(".", $file["name"]);
+    $extension = end($extension);
     
     $maxUploadSize = $_SETTINGS["MAX_UPLOAD_SIZE"] * 1024 * 1024;
 
     if ($maxUploadSize < $file["size"]) {
         return "The file is exceeded the max upload size ({$_SETTINGS["MAX_UPLOAD_SIZE"]} MB)";
     }
 
-    $validExtensionForUpload = [];
+    $validFileForUpload = [];
     switch($type) {
-        case "image":       $validExtensionForUpload = $_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"]; break;
-        case "document":    $validExtensionForUpload = $_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"]; break;
-        case "video":       $validExtensionForUpload = $_SETTINGS["VALID_VIDEO_TYPE_FOR_UPLOAD"]; break;
-        case "audio":       $validExtensionForUpload = $_SETTINGS["VALID_AUDIO_TYPE_FOR_UPLOAD"]; break;
-        case "program":     $validExtensionForUpload = $_SETTINGS["VALID_PROGRAM_TYPE_FOR_UPLOAD"]; break;
-        case 'all':         $validExtensionForUpload = array_merge($_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"], $_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"]); break;
-    }
-    
-    if(!in_array($extensionName, $validExtensionForUpload)) {
-
-        $validExtensionNameList = join(", ", $validExtensionForUpload);
-
-        return "Invalid {$type} type. Only {$validExtensionNameList} {$type} type are allowed to upload";
+        case "image":       $validFileForUpload = $_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"]; break;
+        case "document":    $validFileForUpload = $_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"]; break;
+        case "video":       $validFileForUpload = $_SETTINGS["VALID_VIDEO_TYPE_FOR_UPLOAD"]; break;
+        case "audio":       $validFileForUpload = $_SETTINGS["VALID_AUDIO_TYPE_FOR_UPLOAD"]; break;
+        case "program":     $validFileForUpload = $_SETTINGS["VALID_PROGRAM_TYPE_FOR_UPLOAD"]; break;
+        case 'all':         $validFileForUpload = array_merge($_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"], $_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"]); break;
     }
 
-    /**
-     * If location is set to db then return the image as blob string
-     * Otherwise save the image in the desired location
-     */
-    if($location == "db") {
-        
-        return array (
-            "success"       => true,
-            "imageType"     => $file["type"],
-            "blobString"    => file_get_contents($file["tmp_name"])
-        );
 
-    } else {
-        
-        $uploadDir = DIR_UPLOAD . $location;
+    // Validate both file extension and mime type
+    if( isset( $validFileForUpload[$extension] ) AND in_array( $mimeType, $validFileForUpload[$extension] )  ) {
 
-        if(!is_dir($uploadDir) && !mkdir($uploadDir, 0777, true)) {
-            return "Error creating directory";
-        }
-
-        // If newFileName is not empty then change the file name by given
-        $file_name = rand().$file["name"];
-        if(!empty($newFileName)) {
-
-            $file_extension = explode(".", $file_name);
-            $file_extension = end($file_extension);
-            $file_name = $newFileName . "." . $file_extension;
-
-        }
-
-
-        if(move_uploaded_file($file["tmp_name"], $uploadDir ."/" . $file_name )) {
 
+        /**
+         * If location is set to db then return the image as blob string
+         * Otherwise save the image in the desired location
+         */
+        if($location == "db") {
+            
             return array (
-                "success"      => true,
-                "fileName"     => $file_name
+                "success"       => true,
+                "imageType"     => $file["type"],
+                "blobString"    => file_get_contents($file["tmp_name"])
             );
 
         } else {
+            
+            $uploadDir = DIR_UPLOAD . $location;
 
-            return "Can not upload the file";
+            if(!is_dir($uploadDir) && !mkdir($uploadDir, 0777, true)) {
+                return "Error creating directory";
+            }
 
-        }
+            // If newFileName is not empty then change the file name by given
+            $file_name = rand().$file["name"];
+            if(!empty($newFileName)) {
 
-        /*
-        //upload code here
-        $data=file_get_contents($_FILES[$fileInputName]["tmp_name"]);
+                $file_extension = explode(".", $file_name);
+                $file_extension = end($file_extension);
+                $file_name = $newFileName . "." . $file_extension;
 
-        //upload webp
-        imagewebp(imagecreatefromstring($data),$location.$uploadedFileName.".webp",75);
+            }
 
-        //upload orginal image
 
-        switch($type){
+            if(move_uploaded_file($file["tmp_name"], $uploadDir ."/" . $file_name )) {
 
-            case "jpeg":  imagejpeg(imagecreatefromstring($data),$location.$uploadedFileName.".jpeg",75);
-                          imagejpeg(imagescale(imagecreatefromstring($data), 200, 200), $location.$uploadedFileName."_thumb.jpeg",80);
-                          
-                          break;
-            case "png":   imagepng(imagecreatefromstring($data),$location.$uploadedFileName.".png",75);
-                          imagepng(imagescale(imagecreatefromstring($data), 200, 200), $location.$uploadedFileName."_thumb.png",80);
-                          break;
-            default:      imagejpeg(imagecreatefromstring($data),$location.$uploadedFileName.".jpg",75);
-                          imagejpeg(imagescale(imagecreatefromstring($data), 200, 200), $location.$uploadedFileName."_thumb.jpg",80);
-                          break;
+                return array (
+                    "success"      => true,
+                    "fileName"     => $file_name
+                );
+
+            } else {
+
+                return "Can not upload the file";
+
+            }
 
         }
 
-        //upload webp thumb
-        imagewebp(imagescale(imagecreatefromstring($data), 200, 200), $location.$uploadedFileName."_thumb.webp",80);
-        
 
-        */
+    } else {
 
-    }
+        return "Invalid {$type} type."; // Only {$validExtensionNameList} {$type} type are allowed to upload";
 
+    }
+    
 }
+
+
 function easyUpload_back(
     string $fileInputName, 
     string $type="image",
     string $location="db"
     ) {

Vulnerable code:  * Define allowed mime type.
$_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"] = array("jpeg", "jpg", "png");
$_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"] = array("pdf", "msword", "vnd.openxmlformats-officedocument.wordprocessingml.document", "vnd.ms-excel", "vnd.openxmlformats-officedocument.spreadsheetml.sheet");

$_SETTINGS["VALID_AUDIO_TYPE_FOR_UPLOAD"] = array("mpeg", "ogg", "opus", "aac", "wav", "webm");
function easyUpload( 
    $type = strtolower($type);
    $extensionName = strtolower(explode("/", $file["type"])[1]);
    $validExtensionForUpload = [];
        case "image":       $validExtensionForUpload = $_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"]; break;
        case "document":    $validExtensionForUpload = $_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"]; break;
        case "video":       $validExtensionForUpload = $_SETTINGS["VALID_VIDEO_TYPE_FOR_UPLOAD"]; break;
        case "audio":       $validExtensionForUpload = $_SETTINGS["VALID_AUDIO_TYPE_FOR_UPLOAD"]; break;
        case "program":     $validExtensionForUpload = $_SETTINGS["VALID_PROGRAM_TYPE_FOR_UPLOAD"]; break;
        case 'all':         $validExtensionForUpload = array_merge($_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"], $_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"]); break;
    }
    
    if(!in_array($extensionName, $validExtensionForUpload)) {

        $validExtensionNameList = join(", ", $validExtensionForUpload);

        return "Invalid {$type} type. Only {$validExtensionNameList} {$type} type are allowed to upload";
    /**
     * If location is set to db then return the image as blob string
     * Otherwise save the image in the desired location
     */
    if($location == "db") {
        
        return array (
            "success"       => true,
            "imageType"     => $file["type"],
            "blobString"    => file_get_contents($file["tmp_name"])
        );
    } else {
        
        $uploadDir = DIR_UPLOAD . $location;
        if(!is_dir($uploadDir) && !mkdir($uploadDir, 0777, true)) {
            return "Error creating directory";
        }

        // If newFileName is not empty then change the file name by given
        $file_name = rand().$file["name"];
        if(!empty($newFileName)) {

            $file_extension = explode(".", $file_name);
            $file_extension = end($file_extension);
            $file_name = $newFileName . "." . $file_extension;

        }


        if(move_uploaded_file($file["tmp_name"], $uploadDir ."/" . $file_name )) {
                "success"      => true,
                "fileName"     => $file_name
            return "Can not upload the file";
        }
        /*
        //upload code here
        $data=file_get_contents($_FILES[$fileInputName]["tmp_name"]);
        //upload webp
        imagewebp(imagecreatefromstring($data),$location.$uploadedFileName.".webp",75);
        //upload orginal image
        switch($type){
            case "jpeg":  imagejpeg(imagecreatefromstring($data),$location.$uploadedFileName.".jpeg",75);
                          imagejpeg(imagescale(imagecreatefromstring($data), 200, 200), $location.$uploadedFileName."_thumb.jpeg",80);
                          
                          break;
            case "png":   imagepng(imagecreatefromstring($data),$location.$uploadedFileName.".png",75);
                          imagepng(imagescale(imagecreatefromstring($data), 200, 200), $location.$uploadedFileName."_thumb.png",80);
                          break;
            default:      imagejpeg(imagecreatefromstring($data),$location.$uploadedFileName.".jpg",75);
                          imagejpeg(imagescale(imagecreatefromstring($data), 200, 200), $location.$uploadedFileName."_thumb.jpg",80);
                          break;
        //upload webp thumb
        imagewebp(imagescale(imagecreatefromstring($data), 200, 200), $location.$uploadedFileName."_thumb.webp",80);
        
        */
    }
Fixed code:  * Define allowed extension and mime type.

$_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"] = array(
    "jpeg"  => array("image/jpeg"),
    "jpg"   => array("image/jpeg"),
    "png"   => array("image/png")
);
$_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"] = array(
    "pdf"   => array("application/pdf"),
    "doc"   => array("application/msword"),
    "docx"  => array("vnd.openxmlformats-officedocument.wordprocessingml.document"),
    "xls"   => array("application/vnd.ms-excel"),
    "xlsx"  => array("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
);
$_SETTINGS["VALID_AUDIO_TYPE_FOR_UPLOAD"] = array(
    "oga"   => array("audio/ogg"),
    "opus"  => array("audio/opus"),
    "wav"   => array("audio/wav"),
    "weba"  => array("audio/webm")
);

// Valid video type for upload
$_SETTINGS["VALID_VIDEO_TYPE_FOR_UPLOAD"] = array(
    "mpeg"  => array("video/mpeg"),
    "ogv"   => array("video/ogg"),
    "webm"  => array("video/webm"),
    "mp4"   => array("video/mp4")
);

 function easyUpload( 
    $mimeType = strtolower($file["type"]);
    $extension = explode(".", $file["name"]);
    $extension = end($extension);
    $validFileForUpload = [];
        case "image":       $validFileForUpload = $_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"]; break;
        case "document":    $validFileForUpload = $_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"]; break;
        case "video":       $validFileForUpload = $_SETTINGS["VALID_VIDEO_TYPE_FOR_UPLOAD"]; break;
        case "audio":       $validFileForUpload = $_SETTINGS["VALID_AUDIO_TYPE_FOR_UPLOAD"]; break;
        case "program":     $validFileForUpload = $_SETTINGS["VALID_PROGRAM_TYPE_FOR_UPLOAD"]; break;
        case 'all':         $validFileForUpload = array_merge($_SETTINGS["VALID_IMAGE_TYPE_FOR_UPLOAD"], $_SETTINGS["VALID_DOCUMENT_TYPE_FOR_UPLOAD"]); break;
    // Validate both file extension and mime type
    if( isset( $validFileForUpload[$extension] ) AND in_array( $mimeType, $validFileForUpload[$extension] )  ) {
        /**
         * If location is set to db then return the image as blob string
         * Otherwise save the image in the desired location
         */
        if($location == "db") {
            
                "success"       => true,
                "imageType"     => $file["type"],
                "blobString"    => file_get_contents($file["tmp_name"])
            
            $uploadDir = DIR_UPLOAD . $location;
            if(!is_dir($uploadDir) && !mkdir($uploadDir, 0777, true)) {
                return "Error creating directory";
            }
            // If newFileName is not empty then change the file name by given
            $file_name = rand().$file["name"];
            if(!empty($newFileName)) {
                $file_extension = explode(".", $file_name);
                $file_extension = end($file_extension);
                $file_name = $newFileName . "." . $file_extension;
            }
            if(move_uploaded_file($file["tmp_name"], $uploadDir ."/" . $file_name )) {
                return array (
                    "success"      => true,
                    "fileName"     => $file_name
                );

            } else {

                return "Can not upload the file";

            }
    } else {
        return "Invalid {$type} type."; // Only {$validExtensionNameList} {$type} type are allowed to upload";
    }