CVE-2022-4665 (published 2022-12-23T01:15Z)

Unrestricted Upload of File with Dangerous Type in GitHub repository ampache/ampache prior to 5.5.6.

CVSS v3 base score: 8.8, HIGH (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-434
cwe_name: Unrestricted Upload of File with Dangerous Type
description: The product allows the upload or transfer of dangerous file types that are automatically processed within its environment.
extended_description: 
            
            
            
            
            
         
         

Fix information:
repo_url: https://github.com/ampache/ampache
commit_details: repo_url: https://github.com/ampache/ampache
author: lachlan
author_date: 2022-12-14 17:47:15+10:00
msg: think we good now
repository: repo_url: https://github.com/ampache/ampache
repo_name: ampache/ampache
description: A web based audio/video streaming application and file manager allowing you to access your music & videos from anywhere, using almost any internet enabled device.
repo_language: PHP
owner: ampache
file_changes: filename: CHANGELOG.md
change_type: ModificationType.MODIFY
diff: @@ -18,6 +18,8 @@ There will probably not be another big change to Ampache 5 as work has moved to
 * Missing translation on preferences sidebar
 * Default catalog_filter group could be missing on a new install
 * Gather genre tags when not an array
+* Display webp images
+* Check for a valid image extensions when uploading art
 
 ## API 5.5.6
 

programming_language: Markdown
filename: show_artist_info.inc.php
change_type: ModificationType.MODIFY
diff: @@ -48,8 +48,8 @@ use Ampache\Module\Util\Ui;
     </div>
 </div>
 <div id="item_summary">
-    <?php if (array_key_exists('summary', $biography) && !empty(trim($biography['summary']))) { ?>
-        <?php echo nl2br($biography['summary']); ?>
+    <?php if (array_key_exists('summary', $biography) && !empty($biography['summary'])) { ?>
+        <?php echo nl2br(trim($biography['summary'])); ?>
         <?php
     }?>
 </div>

programming_language: PHP
filename: ampache.sql
change_type: ModificationType.MODIFY
diff: @@ -18,7 +18,7 @@
 -- https://www.phpmyadmin.net/
 --
 -- Host: 192.168.1.20
--- Generation Time: Nov 19, 2022 at 05:49 PM
+-- Generation Time: Dec 08, 2022 at 08:40 AM
 -- Server version: 10.5.15-MariaDB-0+deb11u1
 -- PHP Version: 8.1.11
 
@@ -34,7 +34,7 @@ SET time_zone = "+00:00";
 /*!40101 SET NAMES utf8mb4 */;
 
 --
--- Database: `ampache554`
+-- Database: `ampache556`
 --
 
 -- --------------------------------------------------------

programming_language: SQL
filename: FolderCollectorModule.php
change_type: ModificationType.MODIFY
diff: @@ -85,16 +85,6 @@ final class FolderCollectorModule implements CollectorModuleInterface
         $artist_filename    = $this->configContainer->get('artist_art_preferred_filename');
         $artist_art_folder  = $this->configContainer->get('artist_art_folder');
 
-        // Array of valid extensions
-        $image_extensions = [
-            'bmp',
-            'gif',
-            'jp2',
-            'jpeg',
-            'jpg',
-            'png'
-        ];
-
         $dirs = array();
         if ($art->type == 'album') {
             $media = new Album($art->uid);
@@ -154,7 +144,7 @@ final class FolderCollectorModule implements CollectorModuleInterface
                 $extension = $extension['extension'] ?? '';
 
                 // Make sure it looks like an image file
-                if (!in_array($extension, $image_extensions)) {
+                if (!in_array($extension, Art::VALID_TYPES)) {
                     continue;
                 }
 

programming_language: PHP
filename: AmpacheMpd.php
change_type: ModificationType.MODIFY
diff: @@ -374,7 +374,6 @@ class AmpacheMpd extends localplay_controller
         return $this->_mpd->Pause();
     } // pause
 
-
     /**
      * volume
      * This tells MPD to set the volume to the parameter

programming_language: PHP
filename: UPnPDevice.php
change_type: ModificationType.MODIFY
diff: @@ -35,7 +35,6 @@ class UPnPDevice
         "eventURLs" => array()
     );
 
-
     /**
      * UPnPDevice constructor.
      * @param $descriptionUrl

programming_language: PHP
filename: VlcPlayer.php
change_type: ModificationType.MODIFY
diff: @@ -292,7 +292,6 @@ class VlcPlayer
         return $results;
     } // fullstate
 
-
     /**
      * volume_up
      * This increases the volume of VLC, set to +20 can be changed to your preference

programming_language: PHP
filename: Stream_Playlist.php
change_type: ModificationType.MODIFY
diff: @@ -760,7 +760,6 @@ class Stream_Playlist
         return false;
     } // create_download
 
-
     /**
      * create_ram
      *this functions creates a RAM file for use by Real Player

programming_language: PHP
filename: Update.php
change_type: ModificationType.MODIFY
diff: @@ -2368,8 +2368,6 @@ class Update
         return $retval;
     }
 
-
-
     /**
      * update_370028
      *

programming_language: SQL
filename: Art.php
change_type: ModificationType.MODIFY
diff: @@ -49,6 +49,7 @@ use RuntimeException;
 class Art extends database_object
 {
     protected const DB_TABLENAME = 'art';
+    public const VALID_TYPES     = array('bmp', 'gif', 'jp2', 'jpeg', 'jpg', 'png', 'webp');
 
     /**
      * @var integer $id
@@ -403,8 +404,12 @@ class Art extends database_object
                 /* is the file flac or mp3? */
                 $apic_typeid   = ($fileformat == 'flac' || $fileformat == 'ogg') ? 'typeid' : 'picturetypeid';
                 $apic_mimetype = ($fileformat == 'flac' || $fileformat == 'ogg') ? 'image_mime' : 'mime';
-                $new_pic       = array('data' => $source, 'mime' => $mime,
-                    'picturetypeid' => $current_picturetypeid, 'description' => $description);
+                $new_pic       = array(
+                    'data' => $source,
+                    'mime' => $mime,
+                    'picturetypeid' => $current_picturetypeid,
+                    'description' => $description
+                );
 
                 if (is_null($apics)) {
                     $ndata['attached_picture'][]    = $new_pic;
@@ -414,8 +419,12 @@ class Art extends database_object
                             $idx = $this->check_for_duplicate($apics, $ndata, $new_pic, $apic_typeid);
                             if (is_null($idx)) {
                                 $ndata['attached_picture'][] = $new_pic;
-                                $ndata['attached_picture'][] = array('data' => $apics[0]['data'], 'description' => $apics[0]['description'],
-                                    'mime' => $apics[0]['mime'], 'picturetypeid' => $apics[0]['picturetypeid']);
+                                $ndata['attached_picture'][] = array(
+                                    'data' => $apics[0]['data'],
+                                    'description' => $apics[0]['description'],
+                                    'mime' => $apics[0]['mime'],
+                                    'picturetypeid' => $apics[0]['picturetypeid']
+                                );
                             }
                             break;
                         case 2:
@@ -428,8 +437,12 @@ class Art extends database_object
                                 $ndata['attached_picture'][0] = $new_pic;
                             } else {
                                 $apicsId                              = ($idx == 0) ? 1 : 0;
-                                $ndata['attached_picture'][$apicsId]  = array('data' => $apics[$apicsId]['data'], 'mime' => $apics[$apicsId][$apic_mimetype],
-                                'picturetypeid' => $apics[$apicsId][$apic_typeid], 'description' => $apics[$apicsId]['description']);
+                                $ndata['attached_picture'][$apicsId]  = array(
+                                    'data' => $apics[$apicsId]['data'],
+                                    'mime' => $apics[$apicsId][$apic_mimetype],
+                                    'picturetypeid' => $apics[$apicsId][$apic_typeid],
+                                    'description' => $apics[$apicsId]['description']
+                                );
                             }
 
                             break;
@@ -511,10 +524,10 @@ class Art extends database_object
         $height = (int)($dimensions['height']);
 
         if ($width > 0 && $height > 0) {
-            $minw = (AmpConfig::get('album_art_min_width')) ? AmpConfig::get('album_art_min_width') : 0;
-            $maxw = (AmpConfig::get('album_art_max_width')) ? AmpConfig::get('album_art_max_width') : 0;
-            $minh = (AmpConfig::get('album_art_min_height')) ? AmpConfig::get('album_art_min_height') : 0;
-            $maxh = (AmpConfig::get('album_art_max_height')) ? AmpConfig::get('album_art_max_height') : 0;
+            $minw = AmpConfig::get('album_art_min_width', 0);
+            $maxw = AmpConfig::get('album_art_max_width', 0);
+            $minh = AmpConfig::get('album_art_min_height', 0);
+            $maxh = AmpConfig::get('album_art_max_height', 0);
 
             // minimum width is set and current width is too low
             if ($minw > 0 && $width < $minw) {
@@ -627,9 +640,8 @@ class Art extends database_object
 
     /**
      * read_from_images
-     * @param string $name
      */
-    private static function read_from_images($name = 'blankalbum.png')
+    private static function read_from_images()
     {
         $path = __DIR__ . '/../../../public/images/blankalbum.png';
         if (!Core::is_readable($path)) {
@@ -926,6 +938,10 @@ class Art extends database_object
                 imagepng($thumbnail);
                 $mime_type = image_type_to_mime_type(IMAGETYPE_PNG);
                 break;
+            case 'webp':
+                imagewebp($thumbnail);
+                $mime_type = image_type_to_mime_type(IMAGETYPE_WEBP);
+                break;
             default:
                 $mime_type = null;
         } // resized
@@ -1498,7 +1514,7 @@ class Art extends database_object
             $class_name  = ObjectTypeToClassNameMapper::map($object_type);
             $libitem     = new $class_name($object_id);
             echo "<div class=\"item_art_actions\">";
-            if (Core::get_global('user')->has_access(50) || (Core::get_global('user')->has_access(25) && Core::get_global('user')->id == $libitem->get_user_owner())) {
+            if ((!empty(Core::get_global('user')) && Core::get_global('user')->has_access(50)) || (Core::get_global('user')->has_access(25) && Core::get_global('user')->id == $libitem->get_user_owner())) {
                 echo "<a href=\"javascript:NavigateTo('" . AmpConfig::get('web_path') . "/arts.php?action=show_art_dlg&object_type=" . $object_type . "&object_id=" . $object_id . "&burl=' + getCurrentPage());\">";
                 echo Ui::get_icon('edit', T_('Edit/Find Art'));
                 echo "</a>";

programming_language: PHP
filename: Catalog.php
change_type: ModificationType.MODIFY
diff: @@ -3821,6 +3821,7 @@ abstract class Catalog extends database_object
         $sql = "DELETE FROM `catalog_map` WHERE `catalog_id` = 0";
         Dba::write($sql);
     }
+
     /**
      * Delete catalog filters that might have gone missing
      */

programming_language: PHP
filename: TVShow_Season.php
change_type: ModificationType.MODIFY
diff: @@ -115,7 +115,7 @@ class TVShow_Season extends database_object implements library_item, GarbageColl
         if (parent::is_cached('tvshow_extra', $this->id)) {
             $row = parent::get_from_cache('tvshow_extra', $this->id);
         } else {
-            $sql = "SELECT COUNT(`tvshow_episode`.`id`) AS `episode_count`, `video`.`catalog` AS `catalog_id` FROM `tvshow_episode` LEFT JOIN `video` ON `video`.`id` = `tvshow_episode`.`id` WHERE `tvshow_episode`.`season` = ?GROUP BY `catalog_id`";
+            $sql = "SELECT COUNT(`tvshow_episode`.`id`) AS `episode_count`, `video`.`catalog` AS `catalog_id` FROM `tvshow_episode` LEFT JOIN `video` ON `video`.`id` = `tvshow_episode`.`id` WHERE `tvshow_episode`.`season` = ? GROUP BY `catalog_id`";
 
             $db_results = Dba::read($sql, array($this->id));
             $row        = Dba::fetch_assoc($db_results);

programming_language: PHP
filename: Tag.php
change_type: ModificationType.MODIFY
diff: @@ -553,7 +553,7 @@ class Tag extends database_object implements library_item, GarbageCollectibleInt
         $object_id = (int)($object_id);
 
         $limit = (int)($limit);
-        $sql   = "SELECT `tag_map`.`id`, `tag_map`.`tag_id`, `tag`.`name`, `tag_map`.`user` FROM `tag` LEFT JOIN `tag_map` ON `tag_map`.`tag_id`=`tag`.`id` WHERE `tag`.`is_hidden` = false AND `tag_map`.`object_type` = ? AND `tag_map`.`object_id` = ?LIMIT $limit";
+        $sql   = "SELECT `tag_map`.`id`, `tag_map`.`tag_id`, `tag`.`name`, `tag_map`.`user` FROM `tag` LEFT JOIN `tag_map` ON `tag_map`.`tag_id`=`tag`.`id` WHERE `tag`.`is_hidden` = false AND `tag_map`.`object_type` = ? AND `tag_map`.`object_id` = ? LIMIT $limit";
 
         $db_results = Dba::read($sql, array($type, $object_id));
         $results    = array();

programming_language: PHP
filename: User.php
change_type: ModificationType.MODIFY
diff: @@ -354,7 +354,6 @@ class User extends database_object
         return $catalogs;
     } // get_catalogs
 
-
     /**
      * get_catalogs
      * This returns the catalogs as an array of ids that this user is allowed to access
@@ -365,7 +364,6 @@ class User extends database_object
         return self::get_user_catalogs($this->id);
     } // get_catalogs
 
-
     /**
      * get_preferences
      * This is a little more complicate now that we've got many types of preferences
@@ -1440,8 +1438,11 @@ class User extends database_object
             $path_info      = pathinfo($_FILES['avatar']['name']);
             $upload['file'] = $_FILES['avatar']['tmp_name'];
             $upload['mime'] = 'image/' . $path_info['extension'];
-            $image_data     = Art::get_from_source($upload, 'user');
+            if (!in_array(strtolower($path_info['extension']), Art::VALID_TYPES)) {
+                return false;
+            }
 
+            $image_data = Art::get_from_source($upload, 'user');
             if ($image_data !== '') {
                 return $this->update_avatar($image_data, $upload['mime']);
             }

programming_language: PHP