CVE-2023-6599: Improper Handling of Exceptional Conditions (CWE-755)
value: Missing Standardized Error Handling Mechanism in GitHub repository microweber/microweber prior to 2.0.
CWE description: The product does not handle or incorrectly handles an exceptional condition.
CVSS v3 base score: 4.3
Published: 2023-12-08T00:15Z
Repository: https://github.com/microweber/microweber
Language: PHP
Files changed: src/MicroweberPackages/FileManager/Http/Controllers/PluploadController.php, src/MicroweberPackages/Media/MediaManager.php, src/MicroweberPackages/Media/Traits/MediaTrait.php, src/MicroweberPackages/Media/migrations/2020_07_02_000000_create_media_table.php, src/MicroweberPackages/Media/tests/LegacyMediaTest.php
Commit date: 2023-06-08 17:32:44 +0300
Commit message: update

Diff: diff --git a/src/MicroweberPackages/FileManager/Http/Controllers/PluploadController.php b/src/MicroweberPackages/FileManager/Http/Controllers/PluploadController.php
index 286e0b3f459..9890f301aa0 100644
--- a/src/MicroweberPackages/FileManager/Http/Controllers/PluploadController.php
+++ b/src/MicroweberPackages/FileManager/Http/Controllers/PluploadController.php
@@ -356,13 +356,13 @@ class PluploadController extends Controller
 //$fileName = preg_replace('/[\p{P}\p{Zs}\w\._]+/u', "", $fileName);
 // $fileName = preg_replace('/[^\w\._]+/', '_', $fileName);
         $fileName = preg_replace('/\s+\d+%|\)/', '', $fileName);
         $fileName = preg_replace("/[\/\&%#\$]/", "_", $fileName);
         $fileName = preg_replace("/[\"\']/", " ", $fileName);
-        $fileName = str_replace(array('(', ')', "'", "!", "`", "*", "#"), '_', $fileName);
-        $fileName = str_replace(' ', '_', $fileName);
-        $fileName = str_replace('..', '.', $fileName);
+        $fileName = str_replace(array('(', ')', "'", "!", "`", "*", "#", "<", ">"), '-', $fileName);
+        $fileName = str_replace(' ', '-', $fileName);
+        $fileName = str_replace('..', '-', $fileName);
         $fileName = strtolower($fileName);
         $fileName = mw()->url_manager->clean_url_wrappers($fileName);
         $fileName = substr($fileName, 0, -(strlen($fileNameExtension)));
         $fileName = $fileName . '.' . $fileNameExtension;
 
diff --git a/src/MicroweberPackages/Media/MediaManager.php b/src/MicroweberPackages/Media/MediaManager.php
index d0722500a50..e93b89f9726 100644
--- a/src/MicroweberPackages/Media/MediaManager.php
+++ b/src/MicroweberPackages/Media/MediaManager.php
@@ -378,11 +378,11 @@ class MediaManager
     }
 
     public function save($data)
     {
         $data = app()->html_clean->cleanArray($data);
-
+        $data = xss_clean($data);
         $s = array();
 
         if (isset($data['content-id'])) {
             $t = trim($data['content-id']);
             $s['rel_id'] = $t;
@@ -511,10 +511,13 @@ class MediaManager
                 }
             }
 
             $s['filename'] = $data['src'];
         }
+        if (isset($s['filename']) && !is_string($s['filename'])) {
+           return false;
+        }
 
         if (!isset($data['position']) and !isset($s['id'])) {
             $s['position'] = 9999999;
         }
 
@@ -523,10 +526,11 @@ class MediaManager
             $s['rel_id'] = $t;
         }
 
         if ((!isset($s['id']) or (isset($s['id']) and $s['id'] == 0))
             and isset($s['filename'])
+            and is_string($s['filename'])
             and isset($s['rel_id'])
             and isset($s['rel_type'])
         ) {
             $s['filename'] = str_replace(site_url(), '{SITE_URL}', $s['filename']);
             $check = array();
@@ -538,11 +542,11 @@ class MediaManager
             if (isset($check['id'])) {
                 $s['id'] = $check['id'];
             }
         }
 
-        if (!isset($s['id']) and isset($s['filename']) and !isset($data['media_type'])) {
+        if (!isset($s['id']) and isset($s['filename']) and is_string($s['filename']) and !isset($data['media_type'])) {
             $ext = get_file_extension($s['filename']);
             $data['media_type'] = $this->_guess_media_type_from_file_ext($ext);
         }
 
         if (isset($data['media_type'])) {
@@ -557,15 +561,10 @@ class MediaManager
 
         if (isset($data['image_options'])) {
             $s['image_options'] = @json_encode($data['image_options']);
         }
 
-        if (isset($s['filename']) && is_array($s['filename'])) {
-            if (isset($s['filename']['error'])) {
-                return false;
-            }
-        }
 
         if (isset($s['rel_type']) and isset($s['rel_id'])) {
             $s['rel_id'] = trim($s['rel_id']);
             $table = 'media';
             $s = $this->app->database_manager->extended_save($table, $s);
diff --git a/src/MicroweberPackages/Media/Traits/MediaTrait.php b/src/MicroweberPackages/Media/Traits/MediaTrait.php
index 91a293d0107..31db8f786e6 100644
--- a/src/MicroweberPackages/Media/Traits/MediaTrait.php
+++ b/src/MicroweberPackages/Media/Traits/MediaTrait.php
@@ -80,11 +80,11 @@ trait MediaTrait
                                 'allow_remote_download' => 1,
                                 'rel_type' => 'content',
                                 'rel_id' => $model->id,
                                 'title' => 'Picture',
                                 'media_type' => 'picture',
-                                'src' => $url,
+                                'filename' => $url,
                             ));
                         }
                     }
 
                 }
diff --git a/src/MicroweberPackages/Media/migrations/2020_07_02_000000_create_media_table.php b/src/MicroweberPackages/Media/migrations/2020_07_02_000000_create_media_table.php
index aba927dbe8a..e5a86958f44 100644
--- a/src/MicroweberPackages/Media/migrations/2020_07_02_000000_create_media_table.php
+++ b/src/MicroweberPackages/Media/migrations/2020_07_02_000000_create_media_table.php
@@ -16,11 +16,11 @@ class CreateMediaTable extends Migration
         if (!Schema::hasTable('media')) {
             Schema::create('media', function (Blueprint $table) {
                 $table->id();
                 $table->text('title')->nullable();
                 $table->text('description')->nullable();
-                $table->text('embed_code')->nullable();
+                //$table->text('embed_code')->nullable();
                 $table->text('filename')->nullable();
                 $table->text('media_type')->nullable()->index();
 
                 $table->string('rel_type')->nullable()->index();
                 $table->string('rel_id')->nullable()->index();
diff --git a/src/MicroweberPackages/Media/tests/MediaTestLegacy.php b/src/MicroweberPackages/Media/tests/LegacyMediaTest.php
similarity index 51%
rename from src/MicroweberPackages/Media/tests/MediaTestLegacy.php
rename to src/MicroweberPackages/Media/tests/LegacyMediaTest.php
index 43be36bc4c3..267a88e0000 100644
--- a/src/MicroweberPackages/Media/tests/MediaTestLegacy.php
+++ b/src/MicroweberPackages/Media/tests/LegacyMediaTest.php
@@ -2,20 +2,20 @@
 
 namespace MicroweberPackages\Media\tests;
 
 use MicroweberPackages\Core\tests\TestCase;
 
-class MediaTest extends TestCase
+class LegacyMediaTest extends TestCase
 {
     public function testSaveMedia()
     {
         $picture = array(
             'rel_type' => 'content',
             'rel_id' => 3,
             'title' => 'My new pic',
             'media_type' => 'picture',
-            'src' => 'http://lorempixel.com/400/200/',
+            'filename' => 'http://lorempixel.com/400/200/',
         );
         $saved_pic_id = save_media($picture);
 
         $picture_data = get_media_by_id($saved_pic_id);
 
@@ -33,11 +33,11 @@ class MediaTest extends TestCase
         $picture = array(
             'rel_type' => 'content',
             'rel_id' => 3,
             'title' => 'My new pic to del',
             'media_type' => 'picture',
-            'src' => 'http://lorempixel.com/400/200/',
+            'filename' => 'http://lorempixel.com/400/200/',
         );
         $saved_pic_id = save_media($picture);
         $picture_data = get_media_by_id($saved_pic_id);
         $to_delete = array('id' => $saved_pic_id);
         $delete = delete_media($to_delete);
@@ -46,7 +46,44 @@ class MediaTest extends TestCase
 
         $this->assertEquals($picture_null, false);
         $this->assertEquals(is_array($picture_data), true);
         $this->assertEquals($title, 'My new pic to del');
         $this->assertEquals(!($delete), false);
+    }
+
+    public function testSaveMediaArrayInFilename()
+    {
+        $picture = array(
+            'rel_type' => 'content',
+            'rel_id' => 3,
+            'title' => 'My new pic',
+            'media_type' => 'picture',
+            'filename' => ['http://lorempixel.com/400/200/', 'http://lorempixel.com/400/200/'],
+        );
+        $saved_pic_id = save_media($picture);
+
+        $this->assertFalse($saved_pic_id);
+    }
+    public function testSaveMediaXssFilename()
+    {
+        $xss = '<style>@keyframes x{}</style><xss style="animation-name:x" onanimationend="alert(document.cookie)"></xss>';
+
+        $picture = array(
+            'rel_type' => 'content',
+            'rel_id' => 3,
+            'title' => 'My new pic to xss'.$xss,
+            'description' => 'My new pic description xss'.$xss,
+            'media_type' => 'picture',
+            'filename' => 'http://lorempixel.com/400/200/'.$xss,
+        );
+        $saved_pic_id = save_media($picture);
+        $picture_data = get_media_by_id($saved_pic_id);
+
+        $this->assertNotEquals($picture_data['title'], $picture['title']);
+        $this->assertNotEquals($picture_data['description'], $picture['description']);
+        $this->assertNotEquals($picture_data['filename'], $picture['filename']);
+
+
+
+
     }
 }

Vulnerable code:         $fileName = str_replace(array('(', ')', "'", "!", "`", "*", "#"), '_', $fileName);
        $fileName = str_replace(' ', '_', $fileName);
        $fileName = str_replace('..', '.', $fileName);

        if (!isset($s['id']) and isset($s['filename']) and !isset($data['media_type'])) {
        if (isset($s['filename']) && is_array($s['filename'])) {
            if (isset($s['filename']['error'])) {
                return false;
            }
        }
                                'src' => $url,
                $table->text('embed_code')->nullable();
class MediaTest extends TestCase
            'src' => 'http://lorempixel.com/400/200/',
            'src' => 'http://lorempixel.com/400/200/',
Fixed code:         $fileName = str_replace(array('(', ')', "'", "!", "`", "*", "#", "<", ">"), '-', $fileName);
        $fileName = str_replace(' ', '-', $fileName);
        $fileName = str_replace('..', '-', $fileName);
        $data = xss_clean($data);
        if (isset($s['filename']) && !is_string($s['filename'])) {
           return false;
        }
            and is_string($s['filename'])
        if (!isset($s['id']) and isset($s['filename']) and is_string($s['filename']) and !isset($data['media_type'])) {
                                'filename' => $url,
                //$table->text('embed_code')->nullable();
class LegacyMediaTest extends TestCase
            'filename' => 'http://lorempixel.com/400/200/',
            'filename' => 'http://lorempixel.com/400/200/',
    }

    public function testSaveMediaArrayInFilename()
    {
        $picture = array(
            'rel_type' => 'content',
            'rel_id' => 3,
            'title' => 'My new pic',
            'media_type' => 'picture',
            'filename' => ['http://lorempixel.com/400/200/', 'http://lorempixel.com/400/200/'],
        );
        $saved_pic_id = save_media($picture);

        $this->assertFalse($saved_pic_id);
    }
    public function testSaveMediaXssFilename()
    {
        $xss = '<style>@keyframes x{}</style><xss style="animation-name:x" onanimationend="alert(document.cookie)"></xss>';

        $picture = array(
            'rel_type' => 'content',
            'rel_id' => 3,
            'title' => 'My new pic to xss'.$xss,
            'description' => 'My new pic description xss'.$xss,
            'media_type' => 'picture',
            'filename' => 'http://lorempixel.com/400/200/'.$xss,
        );
        $saved_pic_id = save_media($picture);
        $picture_data = get_media_by_id($saved_pic_id);

        $this->assertNotEquals($picture_data['title'], $picture['title']);
        $this->assertNotEquals($picture_data['description'], $picture['description']);
        $this->assertNotEquals($picture_data['filename'], $picture['filename']);