CVE-2024-32871 (published 2024-06-04T15:15Z)

Pimcore is an Open Source Data & Experience Management Platform. The Pimcore thumbnail generation can be used to flood the server with large files. By changing the file extension or scaling factor of the requested thumbnail, attackers can create files that are much larger in file size than the original. This vulnerability is fixed in 11.2.4.

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

Weakness information:
cwe_id: CWE-770
cwe_name: Allocation of Resources Without Limits or Throttling
description: The product allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated, in violation of the intended security policy for that actor.
extended_description: Code frequently has to work with limited resources, so programmers must be careful to ensure that resources are not consumed too quickly, or too easily.  Without use of quotas, resource limits, or other protection mechanisms, it can be easy for an attacker to consume many resources by rapidly making many requests, or causing larger resources to be used than is needed. When too many resources are allocated, or if a single resource is too large, then it can prevent the code from working correctly, possibly leading to a denial of service.
         

Fix information:
repo_url: https://github.com/pimcore/pimcore
commit_details: repo_url: https://github.com/pimcore/pimcore
author: mattamon
author_date: 2024-05-13 14:48:07+02:00
msg: Fix thumbnail generation if asset or config is null
repository: repo_url: https://github.com/pimcore/pimcore
repo_name: pimcore/pimcore
description: Core Framework for the Open Source Data & Experience Management Platform (PIM, MDM, CDP, DAM, DXP/CMS & Digital Commerce)
repo_language: PHP
owner: pimcore
file_changes: filename: ImageThumbnail.php
change_type: ModificationType.MODIFY
diff: @@ -76,14 +76,15 @@ final class ImageThumbnail implements ImageThumbnailInterface
      */
     public function generate(bool $deferredAllowed = true): void
     {
-        if (!$this->checkAllowedFormats($this->config->getFormat(), $this->asset)) {
-            throw new ThumbnailFormatNotSupportedException();
-        }
-
         $deferred = $deferredAllowed && $this->deferred;
         $generated = false;
 
         if ($this->asset && empty($this->pathReference)) {
+
+            if (!$this->checkAllowedFormats($this->config->getFormat(), $this->asset)) {
+                throw new ThumbnailFormatNotSupportedException();
+            }
+
             $config = $this->getConfig();
             $cacheFileStream = null;
             $config->setFilenameSuffix('page-' . $this->page);

programming_language: PHP
filename: Thumbnail.php
change_type: ModificationType.MODIFY
diff: @@ -112,13 +112,7 @@ final class Thumbnail implements ThumbnailInterface
      */
     public function generate(bool $deferredAllowed = true): void
     {
-        if (!$this->checkAllowedFormats($this->config->getFormat(), $this->asset)) {
-            throw new ThumbnailFormatNotSupportedException();
-        }
-
-        if (!$this->checkMaxScalingFactor($this->config->getHighResolution())) {
-            throw new ThumbnailMaxScalingFactorException();
-        }
+        $this->validate();
 
         $deferred = false;
         $generated = false;
@@ -460,4 +454,22 @@ final class Thumbnail implements ThumbnailInterface
 
         return implode(', ', $srcSetValues);
     }
+
+    /**
+     * @throws ThumbnailFormatNotSupportedException
+     * @throws ThumbnailMaxScalingFactorException
+     */
+    private function validate(): void
+    {
+        if(!$this->asset || !$this->config) {
+            return;
+        }
+        if (!$this->checkAllowedFormats($this->config->getFormat(), $this->asset)) {
+            throw new ThumbnailFormatNotSupportedException();
+        }
+
+        if (!$this->checkMaxScalingFactor($this->config->getHighResolution())) {
+            throw new ThumbnailMaxScalingFactorException();
+        }
+    }
 }

programming_language: PHP
filename: ImageThumbnailTrait.php
change_type: ModificationType.MODIFY
diff: @@ -434,7 +434,7 @@ trait ImageThumbnailTrait
     {
         $format = strtolower($format);
         if($asset) {
-            $original = pathinfo($asset->getRealFullPath(), PATHINFO_EXTENSION);
+            $original = strtolower(pathinfo($asset->getRealFullPath(), PATHINFO_EXTENSION));
             if ($format === $original || $format === 'source') {
                 return true;
             }

programming_language: PHP
filename: ImageThumbnail.php
change_type: ModificationType.MODIFY
diff: @@ -77,20 +77,21 @@ final class ImageThumbnail implements ImageThumbnailInterface
     }
 
     /**
-     * @throws Exception
+     * @throws Exception|\League\Flysystem\FilesystemException|ThumbnailFormatNotSupportedException
      *
      * @internal
      */
     public function generate(bool $deferredAllowed = true): void
     {
-        if (!$this->checkAllowedFormats($this->config->getFormat(), $this->asset)) {
-            throw new ThumbnailFormatNotSupportedException();
-        }
-
         $deferred = $deferredAllowed && $this->deferred;
         $generated = false;
 
         if ($this->asset && empty($this->pathReference)) {
+
+            if (!$this->checkAllowedFormats($this->config->getFormat(), $this->asset)) {
+                throw new ThumbnailFormatNotSupportedException();
+            }
+
             $cs = $this->asset->getCustomSetting('image_thumbnail_time');
             $im = $this->asset->getCustomSetting('image_thumbnail_asset');
 

programming_language: PHP
repo_url: https://github.com/pimcore/pimcore
commit_details: repo_url: https://github.com/pimcore/pimcore
author: Matthias Schuhmayer
author_date: 2024-05-03 13:09:04+02:00
msg: Merge pull request from GHSA-277c-5vvj-9pwx

* Introduce allowed formats and max scale factor

* Add documentation, upgrade notes and use floatNode for max_scale_factor

* Update to max_scaling_factor

* Cast format to lower

* Fix typo
repository: repo_url: https://github.com/pimcore/pimcore
repo_name: pimcore/pimcore
description: Core Framework for the Open Source Data & Experience Management Platform (PIM, MDM, CDP, DAM, DXP/CMS & Digital Commerce)
repo_language: PHP
owner: pimcore
file_changes: filename: Configuration.php
change_type: ModificationType.MODIFY
diff: @@ -352,6 +352,18 @@ final class Configuration implements ConfigurationInterface
                 ->arrayNode('assets')
                 ->addDefaultsIfNotSet()
                 ->children()
+                    ->arrayNode('thumbnails')
+                    ->addDefaultsIfNotSet()
+                        ->children()
+                            ->arrayNode('allowed_formats')
+                                ->defaultValue(['avif', 'eps', 'gif', 'jpeg', 'jpg', 'pjpeg', 'png', 'svg', 'tiff', 'webm', 'webp'])
+                                ->scalarPrototype()->end()
+                            ->end()
+                            ->floatNode('max_scaling_factor')
+                                ->defaultValue(5.0)
+                            ->end()
+                        ->end()
+                    ->end()
                     ->arrayNode('frontend_prefixes')
                         ->addDefaultsIfNotSet()
                         ->children()

programming_language: PHP
filename: 01_Image_Thumbnails.md
change_type: ModificationType.MODIFY
diff: @@ -9,7 +9,8 @@ which are not stored as an asset inside Pimcore.
 > **IMPORTANT**  
 > Use Imagick PECL extension for best results, GDlib is just a fallback with limited functionality
 > (only PNG, JPG, GIF) and less quality!
-> Using ImageMagick Pimcore supports hundreds of formats including: AI, EPS, TIFF, PNG, JPG, GIF, PSD, ...
+> Using ImageMagick Pimcore can support hundreds of formats including: AI, EPS, TIFF, PNG, JPG, GIF, PSD, etc.
+> Not all formats are allowed out of the box. To extend the list [see](./README.md#allowed-formats).
 
 To use the thumbnailing service of Pimcore, you have to create a transformation pipeline first. To do so, open
 _Settings_ > _Thumbnails_ and click on _Add Thumbnail_ to create a new configuration.
@@ -329,6 +330,15 @@ This is a special functionality to allow embedding high resolution (ppi/dpi) ima
 The following is only necessary in special use-cases like Web-to-Print, in typical web-based cases, Pimcore
 automatically adds the `srcset` attribute to `<img>` and `<picture>` tags automatically, so no manual work is necessary.
 
+The high resolution scaling factor is limited to `5.0` eg. `@5x`. Float values are supported.
+If you need to scale an image more than that, you can use the `max_scaling_factor` option in the configuration.
+```yaml
+  pimcore:
+    assets:
+      thumbnails:
+        max_scaling_factor: 6.0
+```
+
 ### Use in the Thumbnail Configuration:
 
 ![High Resolution](../../img/thumbnail_high_resolution.png)

programming_language: Markdown
filename: README.md
change_type: ModificationType.MODIFY
diff: @@ -4,7 +4,32 @@ Pimcore provides a sophisticated thumbnail processing engine for calculating thu
 different output channels Pimcore can calculate and provide optimized images in terms of dimensions, file sizes, formats
 and much more.
 
-This functionality allows true single source publishing with Pimcore. 
+This functionality allows true single source publishing with Pimcore.
+
+### Allowed formats
+Pimcore allows the following formats for thumbnails out of the box:
+`'avif', 'eps', 'gif', 'jpeg', 'jpg', 'pjpeg', 'png', 'svg', 'tiff', 'webm', 'webp'`.
+
+If you want to use a different format, you can easily extend the list of supported formats.
+Keep in mind that you must copy the whole list of formats and add your desired format to it.
+```yaml
+pimcore:
+    assets:
+        thumbnails:
+            allowed_formats:
+                - 'avif'
+                - 'eps'
+                - 'gif'
+                - 'jpeg'
+                - 'jpg'
+                - 'pjpeg'
+                - 'png'
+                - 'svg'
+                - 'tiff'
+                - 'webm'
+                - 'webp'
+                - 'pdf' # Add your desired format here
+```
 
 ##### Thumbnails are available for following file types: 
 * [Image Thumbnails](./01_Image_Thumbnails.md)

programming_language: Markdown
filename: README.md
change_type: ModificationType.MODIFY
diff: @@ -1,5 +1,35 @@
 # Upgrade Notes
 
+## Pimcore 11.2.4
+### Assets Thumbnails
+- Thumbnail generation for Assets, Documents and Videos now only support the following formats out of the box: `'avif', 'eps', 'gif', 'jpeg', 'jpg', 'pjpeg', 'png', 'svg', 'tiff', 'webm', 'webp'`.
+- You can extend this list by adding your formats on the bottom: 
+```yaml
+  pimcore:
+    assets:
+      thumbnails:
+        allowed_formats:
+          - 'avif'
+          - 'eps'
+          - 'gif'
+          - 'jpeg'
+          - 'jpg'
+          - 'pjpeg'
+          - 'png'
+          - 'svg'
+          - 'tiff'
+          - 'webm'
+          - 'webp'
+          - 'pdf' # Add your desired format here
+```
+- High resolution scaling factor for image thumbnails has now been limited to a maximum of `5.0`. If you need to scale an image more than that, you can use the `max_scaling_factor` option in the configuration.
+```yaml
+  pimcore:
+    assets:
+      thumbnails:
+        max_scaling_factor: 6.0
+```
+
 ## Pimcore 11.2.0
 ### Elements
 #### [Documents]:

programming_language: Markdown
filename: ImageThumbnail.php
change_type: ModificationType.MODIFY
diff: @@ -24,6 +24,7 @@ use Pimcore\Logger;
 use Pimcore\Model;
 use Pimcore\Model\Asset\Image;
 use Pimcore\Model\Exception\NotFoundException;
+use Pimcore\Model\Exception\ThumbnailFormatNotSupportedException;
 use Pimcore\Tool\Storage;
 use Symfony\Component\EventDispatcher\GenericEvent;
 use Symfony\Component\Lock\LockFactory;
@@ -70,8 +71,15 @@ final class ImageThumbnail implements ImageThumbnailInterface
         return $path;
     }
 
+    /**
+     * @throws ThumbnailFormatNotSupportedException
+     */
     public function generate(bool $deferredAllowed = true): void
     {
+        if (!$this->checkAllowedFormats($this->config->getFormat())) {
+            throw new ThumbnailFormatNotSupportedException();
+        }
+
         $deferred = $deferredAllowed && $this->deferred;
         $generated = false;
 

programming_language: PHP
filename: Thumbnail.php
change_type: ModificationType.MODIFY
diff: @@ -24,6 +24,8 @@ use Pimcore\Model\Asset\Image;
 use Pimcore\Model\Asset\Image\Thumbnail\Config;
 use Pimcore\Model\Asset\Thumbnail\ImageThumbnailTrait;
 use Pimcore\Model\Exception\NotFoundException;
+use Pimcore\Model\Exception\ThumbnailFormatNotSupportedException;
+use Pimcore\Model\Exception\ThumbnailMaxScalingFactorException;
 use Pimcore\Tool;
 use Symfony\Component\EventDispatcher\GenericEvent;
 
@@ -103,10 +105,20 @@ final class Thumbnail implements ThumbnailInterface
     }
 
     /**
+     * @throws ThumbnailFormatNotSupportedException
+     * @throws ThumbnailMaxScalingFactorException
      * @internal
      */
     public function generate(bool $deferredAllowed = true): void
     {
+        if (!$this->checkAllowedFormats($this->config->getFormat(), $this->asset)) {
+            throw new ThumbnailFormatNotSupportedException();
+        }
+
+        if (!$this->checkMaxScalingFactor($this->config->getHighResolution())) {
+            throw new ThumbnailMaxScalingFactorException();
+        }
+
         $deferred = false;
         $generated = false;
 

programming_language: PHP
filename: ImageThumbnailTrait.php
change_type: ModificationType.MODIFY
diff: @@ -16,6 +16,7 @@ declare(strict_types=1);
 
 namespace Pimcore\Model\Asset\Thumbnail;
 
+use Pimcore\Config as PimcoreConfig;
 use Pimcore\Helper\TemporaryFileHelperTrait;
 use Pimcore\Model\Asset;
 use Pimcore\Model\Asset\Image;
@@ -428,4 +429,28 @@ trait ImageThumbnailTrait
 
         return $thumb;
     }
+
+    private function checkAllowedFormats(string $format, ?Asset $asset = null): bool
+    {
+        $format = strtolower($format);
+        if($asset) {
+            $original = pathinfo($asset->getRealFullPath(),  PATHINFO_EXTENSION);
+            if ($format === $original || $format === 'source') {
+                return true;
+            }
+        }
+
+        $assetConfig = PimcoreConfig::getSystemConfiguration('assets');
+        return in_array(
+            $format,
+            $assetConfig['thumbnails']['allowed_formats'],
+            true
+        );
+    }
+
+    private function checkMaxScalingFactor(float $scalingFactor): bool
+    {
+        $assetConfig = PimcoreConfig::getSystemConfiguration('assets');
+        return $scalingFactor <= $assetConfig['thumbnails']['max_scaling_factor'];
+    }
 }

programming_language: PHP
filename: ImageThumbnail.php
change_type: ModificationType.MODIFY
diff: @@ -16,12 +16,14 @@ declare(strict_types=1);
 
 namespace Pimcore\Model\Asset\Video;
 
+use Exception;
 use Pimcore\Event\AssetEvents;
 use Pimcore\Event\FrontendEvents;
 use Pimcore\File;
 use Pimcore\Logger;
 use Pimcore\Model;
 use Pimcore\Model\Asset\Image;
+use Pimcore\Model\Exception\ThumbnailFormatNotSupportedException;
 use Pimcore\Tool\Storage;
 use Symfony\Component\EventDispatcher\GenericEvent;
 use Symfony\Component\Lock\LockFactory;
@@ -75,12 +77,16 @@ final class ImageThumbnail implements ImageThumbnailInterface
     }
 
     /**
-     * @throws \Exception
+     * @throws Exception
      *
      * @internal
      */
     public function generate(bool $deferredAllowed = true): void
     {
+        if (!$this->checkAllowedFormats($this->config->getFormat())) {
+            throw new ThumbnailFormatNotSupportedException();
+        }
+
         $deferred = $deferredAllowed && $this->deferred;
         $generated = false;
 

programming_language: PHP
filename: ThumbnailFormatNotSupportedException.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,23 @@
+<?php
+declare(strict_types=1);
+
+/**
+ * Pimcore
+ *
+ * This source file is available under two different licenses:
+ * - GNU General Public License version 3 (GPLv3)
+ * - Pimcore Commercial License (PCL)
+ * Full copyright and license information is available in
+ * LICENSE.md which is distributed with this source code.
+ *
+ *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
+ *  @license    http://www.pimcore.org/license     GPLv3 and PCL
+ */
+
+namespace Pimcore\Model\Exception;
+
+use Exception;
+
+final class ThumbnailFormatNotSupportedException extends Exception
+{
+}

programming_language: PHP
filename: ThumbnailMaxScalingFactorException.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,23 @@
+<?php
+declare(strict_types=1);
+
+/**
+ * Pimcore
+ *
+ * This source file is available under two different licenses:
+ * - GNU General Public License version 3 (GPLv3)
+ * - Pimcore Commercial License (PCL)
+ * Full copyright and license information is available in
+ * LICENSE.md which is distributed with this source code.
+ *
+ *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
+ *  @license    http://www.pimcore.org/license     GPLv3 and PCL
+ */
+
+namespace Pimcore\Model\Exception;
+
+use Exception;
+
+final class ThumbnailMaxScalingFactorException extends Exception
+{
+}

programming_language: PHP