CVE-2019-10867: Deserialization of Untrusted Data (CWE-502)
value: An issue was discovered in Pimcore before 5.7.1. An attacker with classes permission can send a POST request to /admin/class/bulk-commit, which will make it possible to exploit the unserialize function when passing untrusted values in the data parameter to bundles/AdminBundle/Controller/Admin/DataObject/ClassController.php.
CWE description: The product deserializes untrusted data without sufficiently verifying that the resulting data will be valid.
CVSS v3 base score: 8.8
Published: 2019-04-04T18:29Z
Repository: https://github.com/pimcore/pimcore
Language: PHP
Files changed: bundles/AdminBundle/Controller/Admin/DataObject/ClassController.php
Commit date: 2019-03-19 15:59:11 +0100
Commit message: [Object] optimized bulk import

Diff: diff --git a/bundles/AdminBundle/Controller/Admin/DataObject/ClassController.php b/bundles/AdminBundle/Controller/Admin/DataObject/ClassController.php
index 5bd3b66ef6..115f172244 100644
--- a/bundles/AdminBundle/Controller/Admin/DataObject/ClassController.php
+++ b/bundles/AdminBundle/Controller/Admin/DataObject/ClassController.php
@@ -22,13 +22,15 @@ use Pimcore\Event\AdminEvents;
 use Pimcore\Logger;
 use Pimcore\Model;
 use Pimcore\Model\Asset;
 use Pimcore\Model\DataObject;
 use Pimcore\Model\Document;
+use Pimcore\Tool\Session;
 use Symfony\Component\EventDispatcher\GenericEvent;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
 use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
 use Symfony\Component\Routing\Annotation\Route;
 
 /**
@@ -1345,13 +1347,17 @@ class ClassController extends AdminController implements EventedControllerInterf
         $result = [];
 
         $tmpName = $_FILES['Filedata']['tmp_name'];
         $json = file_get_contents($tmpName);
 
-        $tmpName = PIMCORE_SYSTEM_TEMP_DIRECTORY . '/bulk-import.tmp';
+        $tmpName = PIMCORE_SYSTEM_TEMP_DIRECTORY . '/bulk-import-' . uniqid() . '.tmp';
         file_put_contents($tmpName, $json);
 
+        Session::useSession(function (AttributeBagInterface $session) use ($tmpName) {
+            $session->set('class_bulk_import_file', $tmpName);
+        }, 'pimcore_objects');
+
         $json = json_decode($json, true);
 
         foreach ($json as $groupName => $group) {
             foreach ($group as $groupItem) {
                 $displayName = null;
@@ -1361,11 +1367,11 @@ class ClassController extends AdminController implements EventedControllerInterf
                     $icon = 'class';
                 } elseif ($groupName == 'customlayout') {
                     $className = $groupItem['className'];
 
                     $layoutData = ['className' => $className, 'name' => $groupItem['name']];
-                    $name = serialize($layoutData);
+                    $name = json_encode($layoutData);
                     $displayName = $className . ' / ' . $groupItem['name'];
                     $icon = 'database_lightning';
                 } else {
                     if ($groupName == 'objectbrick') {
                         $icon = 'objectbricks';
@@ -1380,11 +1386,11 @@ class ClassController extends AdminController implements EventedControllerInterf
                 }
                 $result[] = ['icon' => $icon, 'checked' => true, 'type' => $groupName, 'name' => $name, 'displayName' => $displayName];
             }
         }
 
-        $response = $this->adminJson(['success' => true, 'filename' => $tmpName, 'data' => $result]);
+        $response = $this->adminJson(['success' => true, 'data' => $result]);
         $response->headers->set('Content-Type', 'text/html');
 
         return $response;
     }
 
@@ -1402,13 +1408,14 @@ class ClassController extends AdminController implements EventedControllerInterf
      *
      * @throws \Exception
      */
     public function bulkCommitAction(Request $request)
     {
-        $filename = $request->get('filename');
         $data = json_decode($request->get('data'), true);
 
+        $session = Session::get('pimcore_objects');
+        $filename = $session->get('class_bulk_import_file');
         $json = @file_get_contents($filename);
         $json = json_decode($json, true);
 
         $type = $data['type'];
         $name = $data['name'];
@@ -1449,11 +1456,11 @@ class ClassController extends AdminController implements EventedControllerInterf
                 }
                 $success = DataObject\ClassDefinition\Service::importFieldCollectionFromJson($fieldCollection, json_encode($item), true);
 
                 return $this->adminJson(['success' => $success !== false]);
             } elseif ($type == 'customlayout') {
-                $layoutData = unserialize($data['name']);
+                $layoutData = json_decode($data['name'], true);
                 $className = $layoutData['className'];
                 $layoutName = $layoutData['name'];
 
                 if ($item['name'] == $layoutName && $item['className'] == $className) {
                     $class = DataObject\ClassDefinition::getByName($className);

Vulnerable code:         $tmpName = PIMCORE_SYSTEM_TEMP_DIRECTORY . '/bulk-import.tmp';
                    $name = serialize($layoutData);
        $response = $this->adminJson(['success' => true, 'filename' => $tmpName, 'data' => $result]);
        $filename = $request->get('filename');
                $layoutData = unserialize($data['name']);
Fixed code: use Pimcore\Tool\Session;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
        $tmpName = PIMCORE_SYSTEM_TEMP_DIRECTORY . '/bulk-import-' . uniqid() . '.tmp';
        Session::useSession(function (AttributeBagInterface $session) use ($tmpName) {
            $session->set('class_bulk_import_file', $tmpName);
        }, 'pimcore_objects');

                    $name = json_encode($layoutData);
        $response = $this->adminJson(['success' => true, 'data' => $result]);
        $session = Session::get('pimcore_objects');
        $filename = $session->get('class_bulk_import_file');
                $layoutData = json_decode($data['name'], true);