CVE-2020-27387: Unrestricted Upload of File with Dangerous Type (CWE-434)
value: An unrestricted file upload issue in HorizontCMS through 1.0.0-beta allows an authenticated remote attacker (with access to the FileManager) to upload and execute arbitrary PHP code by uploading a PHP payload, and then using the FileManager's rename function to provide the payload (which will receive a random name on the server) with the PHP extension, and finally executing the PHP file via an HTTP GET request to /storage/<php_file_name>. NOTE: the vendor has patched this while leaving the version number at 1.0.0-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: 2020-11-05T02:15Z
Repository: https://github.com/ttimot24/HorizontCMS
Language: PHP
Files changed: app/Controllers/FileManagerController.php
Commit date: 2020-10-23 20:06:33 +0200
Commit message: Security bug fix.

Diff: diff --git a/app/Controllers/FileManagerController.php b/app/Controllers/FileManagerController.php
index b4733dc..2fd9688 100644
--- a/app/Controllers/FileManagerController.php
+++ b/app/Controllers/FileManagerController.php
@@ -8,10 +8,14 @@ use Illuminate\Support\Facades\Storage;
 use \Illuminate\Http\File;
 
 class FileManagerController extends Controller{
  
 
+    private function validationRegex(){
+        return '/^.*\.('.implode('|',["php","php5","php7"]).')$/i';
+    }
+
 
     /**
      * Display a listing of the resource.
      *
      * @return \Illuminate\Http\Response
@@ -58,11 +62,14 @@ class FileManagerController extends Controller{
         if($this->request->isMethod('POST')){
 
             if ($this->request->hasFile('up_file')){
 
                 foreach($this->request->up_file as $file){
-                   $images[] = $file->store(str_replace("storage/", "", $this->request->input('dir_path')));
+                    
+                    if(!preg_match($this->validationRegex(), strtolower($file))){
+                        $images[] = $file->store(str_replace("storage/", "", $this->request->input('dir_path')));
+                    }
                 }
 
                 if($this->request->ajax()){
                     return response()->json(['success' => 'Files uploaded successfully!', 'uploadedFileNames' => $images ]);
                 }
@@ -221,11 +228,13 @@ class FileManagerController extends Controller{
 
     public function rename(){
 
         if($this->request->isMethod('POST')){
 
-            if(\Storage::move($this->request->input('old_file'), $this->request->input('new_file'))){
+            $new_file = $this->request->input('new_file');
+
+            if(!preg_match($this->validationRegex(), strtolower($new_file)) && \Storage::move($this->request->input('old_file'), $new_file)){
                 if($this->request->ajax()){
                     return response()->json(['success' => trans('File successfully renamed!')]);
                 }
             }else{
                 if($this->request->ajax()){

Vulnerable code:                    $images[] = $file->store(str_replace("storage/", "", $this->request->input('dir_path')));
            if(\Storage::move($this->request->input('old_file'), $this->request->input('new_file'))){
Fixed code:     private function validationRegex(){
        return '/^.*\.('.implode('|',["php","php5","php7"]).')$/i';
    }

                    
                    if(!preg_match($this->validationRegex(), strtolower($file))){
                        $images[] = $file->store(str_replace("storage/", "", $this->request->input('dir_path')));
                    }
            $new_file = $this->request->input('new_file');

            if(!preg_match($this->validationRegex(), strtolower($new_file)) && \Storage::move($this->request->input('old_file'), $new_file)){