VYPR
Moderate severityNVD Advisory· Published Nov 15, 2023· Updated Aug 29, 2024

Full Path Disclosure via re-export document in pimcore/admin-ui-classic-bundle

CVE-2023-47636

Description

The Pimcore Admin Classic Bundle provides a Backend UI for Pimcore. Full Path Disclosure (FPD) vulnerabilities enable the attacker to see the path to the webroot/file. e.g.: /home/omg/htdocs/file/. Certain vulnerabilities, such as using the load_file() (within a SQL Injection) query to view the page source, require the attacker to have the full path to the file they wish to view. In the case of pimcore, the fopen() function here doesn't have an error handle when the file doesn't exist on the server so the server response raises the full path "fopen(/var/www/html/var/tmp/export-{ uniqe id}.csv)". This issue has been patched in commit 10d178ef771 which has been included in release version 1.2.1. Users are advised to upgrade. There are no known workarounds for this vulnerability.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
pimcore/admin-ui-classic-bundlePackagist
< 1.2.11.2.1

Affected products

1

Patches

1
10d178ef7710

Grid Export - Catch unable to read file exception (#342)

2 files changed · +95 74
  • src/Controller/Admin/Asset/AssetHelperController.php+32 26 modified
    @@ -26,8 +26,8 @@
     use Pimcore\Bundle\AdminBundle\Model\GridConfigShare;
     use Pimcore\Bundle\AdminBundle\Tool;
     use Pimcore\Db;
    +use Pimcore\File;
     use Pimcore\Loader\ImplementationLoader\Exception\UnsupportedException;
    -use Pimcore\Localization\LocaleServiceInterface;
     use Pimcore\Logger;
     use Pimcore\Model\Asset;
     use Pimcore\Model\Element;
    @@ -722,17 +722,13 @@ public function getExportJobsAction(Request $request, GridHelperService $gridHel
         /**
          * @Route("/do-export", name="pimcore_admin_asset_assethelper_doexport", methods={"POST"})
          *
    -     * @param Request $request
    -     * @param LocaleServiceInterface $localeService
    -     *
    -     * @return JsonResponse
    +     * @throws FilesystemException
          */
    -    public function doExportAction(Request $request, LocaleServiceInterface $localeService): JsonResponse
    +    public function doExportAction(Request $request): JsonResponse
         {
    -        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
    +        $fileHandle = File::getValidFilename($request->get('fileHandle'));
             $ids = $request->get('ids');
    -        $settings = $request->get('settings');
    -        $settings = json_decode($settings, true);
    +        $settings = json_decode($request->get('settings'), true);
             $delimiter = $settings['delimiter'] ?? ';';
             $language = str_replace('default', '', $request->get('language'));
     
    @@ -752,27 +748,37 @@ public function doExportAction(Request $request, LocaleServiceInterface $localeS
     
             $csv = $this->getCsvData($request, $language, $list, $fields, $addTitles);
     
    -        $storage = Storage::get('temp');
    -        $csvFile = $this->getCsvFile($fileHandle);
    +        try {
    +            $storage = Storage::get('temp');
    +            $csvFile = $this->getCsvFile($fileHandle);
     
    -        $fileStream = $storage->readStream($csvFile);
    +            $fileStream = $storage->readStream($csvFile);
     
    -        $temp = tmpfile();
    -        stream_copy_to_stream($fileStream, $temp, null, 0);
    +            $temp = tmpfile();
    +            stream_copy_to_stream($fileStream, $temp, null, 0);
     
    -        $firstLine = true;
    -        foreach ($csv as $line) {
    -            if ($addTitles && $firstLine) {
    -                $firstLine = false;
    -                $line = implode($delimiter, $line) . "\r\n";
    -                fwrite($temp, $line);
    -            } else {
    -                fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line)) . "\r\n");
    +            $firstLine = true;
    +            foreach ($csv as $line) {
    +                if ($addTitles && $firstLine) {
    +                    $firstLine = false;
    +                    $line = implode($delimiter, $line) . "\r\n";
    +                    fwrite($temp, $line);
    +                } else {
    +                    fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line)) . "\r\n");
    +                }
                 }
    +            $storage->writeStream($csvFile, $temp);
    +        } catch (UnableToReadFile $exception) {
    +            Logger::err($exception->getMessage());
    +
    +            return $this->adminJson(
    +                [
    +                    'success' => false,
    +                    'message' => sprintf('export file not found: %s', $fileHandle)
    +                ]
    +            );
             }
     
    -        $storage->writeStream($csvFile, $temp);
    -
             return $this->adminJson(['success' => true]);
         }
     
    @@ -860,7 +866,7 @@ protected function getCsvFile(string $fileHandle): string
         public function downloadCsvFileAction(Request $request): Response
         {
             $storage = Storage::get('temp');
    -        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
    +        $fileHandle = File::getValidFilename($request->get('fileHandle'));
             $csvFile = $this->getCsvFile($fileHandle);
     
             try {
    @@ -893,7 +899,7 @@ public function downloadCsvFileAction(Request $request): Response
         public function downloadXlsxFileAction(Request $request, GridHelperService $gridHelperService): BinaryFileResponse
         {
             $storage = Storage::get('temp');
    -        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
    +        $fileHandle = File::getValidFilename($request->get('fileHandle'));
             $csvFile = $this->getCsvFile($fileHandle);
     
             try {
    
  • src/Controller/Admin/DataObject/DataObjectHelperController.php+63 48 modified
    @@ -26,9 +26,11 @@
     use Pimcore\Bundle\AdminBundle\Model\GridConfigShare;
     use Pimcore\Config;
     use Pimcore\Db;
    +use Pimcore\File;
     use Pimcore\Localization\LocaleServiceInterface;
     use Pimcore\Logger;
     use Pimcore\Model\DataObject;
    +use Pimcore\Model\DataObject\Listing;
     use Pimcore\Model\User;
     use Pimcore\Security\SecurityHelper;
     use Pimcore\Tool;
    @@ -1283,20 +1285,17 @@ public function getExportJobsAction(Request $request, GridHelperService $gridHel
         /**
          * @Route("/do-export", name="doexport", methods={"POST"})
          *
    -     * @param Request $request
    -     * @param LocaleServiceInterface $localeService
    -     * @param EventDispatcherInterface $eventDispatcher
    -     *
    -     * @return JsonResponse
    -     *
    -     * @throws \Exception
    +     * @throws \Exception|FilesystemException
          */
    -    public function doExportAction(Request $request, LocaleServiceInterface $localeService, EventDispatcherInterface $eventDispatcher): JsonResponse
    +    public function doExportAction(
    +        Request $request,
    +        LocaleServiceInterface $localeService,
    +        EventDispatcherInterface $eventDispatcher
    +    ): JsonResponse
         {
    -        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
    +        $fileHandle = File::getValidFilename($request->get('fileHandle'));
             $ids = $request->get('ids');
    -        $settings = $request->get('settings');
    -        $settings = json_decode($settings, true);
    +        $settings = json_decode($request->get('settings'), true);
             $delimiter = $settings['delimiter'] ?? ';';
             $header = $settings['header'] ?? 'title';
     
    @@ -1308,13 +1307,13 @@ public function doExportAction(Request $request, LocaleServiceInterface $localeS
             $class = DataObject\ClassDefinition::getById($request->get('classId'));
     
             if (!$class) {
    -            throw new \Exception('No class definition found');
    +            throw new \InvalidArgumentException('No class definition found');
             }
     
             $className = $class->getName();
             $listClass = '\\Pimcore\\Model\\DataObject\\' . ucfirst($className) . '\\Listing';
     
    -        /** @var \Pimcore\Model\DataObject\Listing $list */
    +        /** @var Listing $list */
             $list = new $listClass();
     
             $quotedIds = [];
    @@ -1340,56 +1339,72 @@ public function doExportAction(Request $request, LocaleServiceInterface $localeS
     
             $requestedLanguage = $this->extractLanguage($request);
     
    -        $contextFromRequest = $request->get('context');
    -        if ($contextFromRequest) {
    -            $contextFromRequest = json_decode($contextFromRequest, true);
    -        }
    -
             $context = [
                 'source' => 'pimcore-export',
             ];
     
    -        if (is_array($contextFromRequest)) {
    +        $contextFromRequest = $request->get('context');
    +        if ($contextFromRequest) {
    +            $contextFromRequest = json_decode($contextFromRequest, true);
                 $context = array_merge($context, $contextFromRequest);
             }
     
    -        $csv = DataObject\Service::getCsvData($requestedLanguage, $localeService, $list, $fields, $header, $addTitles, $context);
    +        $csv = DataObject\Service::getCsvData(
    +            $requestedLanguage,
    +            $localeService,
    +            $list,
    +            $fields,
    +            $header,
    +            $addTitles,
    +            $context
    +        );
     
    -        $storage = Storage::get('temp');
    -        $csvFile = $this->getCsvFile($fileHandle);
    -
    -        $fileStream = $storage->readStream($csvFile);
    -
    -        $temp = tmpfile();
    -        stream_copy_to_stream($fileStream, $temp, null, 0);
    -
    -        $firstLine = true;
    +        try {
    +            $storage = Storage::get('temp');
    +            $csvFile = $this->getCsvFile($fileHandle);
     
    -        if ($request->get('initial') && $header === 'no_header') {
    -            array_shift($csv);
    -            $firstLine = false;
    -        }
    +            $fileStream = $storage->readStream($csvFile);
     
    -        $lineCount = count($csv);
    +            $temp = tmpfile();
    +            stream_copy_to_stream($fileStream, $temp, null, 0);
     
    -        if (!$addTitles && $lineCount > 0) {
    -            fwrite($temp, "\r\n");
    -        }
    +            $firstLine = true;
     
    -        for ($i = 0; $i < $lineCount; $i++) {
    -            $line = $csv[$i];
    -            if ($addTitles && $firstLine) {
    +            if ($request->get('initial') && $header === 'no_header') {
    +                array_shift($csv);
                     $firstLine = false;
    -                $line = implode($delimiter, $line);
    -                fwrite($temp, $line);
    -            } else {
    -                fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line)));
                 }
    -            if ($i < $lineCount - 1) {
    +
    +            $lineCount = count($csv);
    +
    +            if (!$addTitles && $lineCount > 0) {
                     fwrite($temp, "\r\n");
                 }
    +
    +            for ($i = 0; $i < $lineCount; $i++) {
    +                $line = $csv[$i];
    +                if ($addTitles && $firstLine) {
    +                    $firstLine = false;
    +                    $line = implode($delimiter, $line);
    +                    fwrite($temp, $line);
    +                } else {
    +                    fwrite($temp, implode($delimiter, array_map([$this, 'encodeFunc'], $line)));
    +                }
    +                if ($i < $lineCount - 1) {
    +                    fwrite($temp, "\r\n");
    +                }
    +            }
    +            $storage->writeStream($csvFile, $temp);
    +        } catch (UnableToReadFile $exception) {
    +            Logger::err($exception->getMessage());
    +
    +            return $this->adminJson(
    +                [
    +                    'success' => false,
    +                    'message' => sprintf('export file not found: %s', $fileHandle)
    +                ]
    +            );
             }
    -        $storage->writeStream($csvFile, $temp);
     
             return $this->adminJson(['success' => true]);
         }
    @@ -1412,7 +1427,7 @@ public function encodeFunc(string $value): string
         public function downloadCsvFileAction(Request $request): Response
         {
             $storage = Storage::get('temp');
    -        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
    +        $fileHandle = File::getValidFilename($request->get('fileHandle'));
             $csvFile = $this->getCsvFile($fileHandle);
     
             try {
    @@ -1445,7 +1460,7 @@ public function downloadCsvFileAction(Request $request): Response
         public function downloadXlsxFileAction(Request $request, GridHelperService $gridHelperService): BinaryFileResponse
         {
             $storage = Storage::get('temp');
    -        $fileHandle = \Pimcore\File::getValidFilename($request->get('fileHandle'));
    +        $fileHandle = File::getValidFilename($request->get('fileHandle'));
             $csvFile = $this->getCsvFile($fileHandle);
     
             try {
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.