[SECURITY] Respect permissions of storages in a file collection 94/53894/2
authorGeorg Ringer <georg.ringer@gmail.com>
Tue, 5 Sep 2017 09:36:29 +0000 (11:36 +0200)
committerOliver Hader <oliver.hader@typo3.org>
Tue, 5 Sep 2017 09:36:30 +0000 (11:36 +0200)
If a user creates a sys_file_collection record, only those
storage records must be shown which are allowed for the
user.

Resolves: #82029
Releases: master, 8.7, 7.6
Security-Commit: 3434e003fe61229e099fb80328ceda58e52c2eb0
Security-Bulletin: TYPO3-CORE-SA-2017-005
Change-Id: I41ea240e36b2a2834d385836477958652b3116a8
Reviewed-on: https://review.typo3.org/53894
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
typo3/sysext/backend/Classes/Form/FormDataProvider/AbstractItemProvider.php
typo3/sysext/backend/Classes/Form/FormDataProvider/TcaSelectItems.php
typo3/sysext/core/Classes/Resource/Service/UserFileMountService.php

index 534f74a..2103fac 100644 (file)
@@ -679,6 +679,43 @@ abstract class AbstractItemProvider
     }
 
     /**
+     * Remove items if sys_file_storage is not allowed for non-admin users.
+     *
+     * Used by TcaSelectItems data providers
+     *
+     * @param array $result Result array
+     * @param string $fieldName Current handle field name
+     * @param array $items Incoming items
+     * @return array Modified item array
+     */
+    protected function removeItemsByUserStorageRestriction(array $result, $fieldName, array $items)
+    {
+        $referencedTableName = null;
+        if (isset($result['processedTca']['columns'][$fieldName]['config']['foreign_table'])) {
+            $referencedTableName = $result['processedTca']['columns'][$fieldName]['config']['foreign_table'];
+        }
+        if ($referencedTableName !== 'sys_file_storage') {
+            return $items;
+        }
+
+        $allowedStorageIds = array_map(
+            function (\TYPO3\CMS\Core\Resource\ResourceStorage $storage) {
+                return $storage->getUid();
+            },
+            $this->getBackendUser()->getFileStorages()
+        );
+
+        return array_filter(
+            $items,
+            function (array $item) use ($allowedStorageIds) {
+                $itemValue = isset($item[1]) ? $item[1] : null;
+                return empty($itemValue)
+                    || in_array((int)$itemValue, $allowedStorageIds, true);
+            }
+        );
+    }
+
+    /**
      * Returns an array with the exclude fields as defined in TCA and FlexForms
      * Used for listing the exclude fields in be_groups forms.
      *
index 79fc498..5fc089e 100644 (file)
@@ -50,8 +50,11 @@ class TcaSelectItems extends AbstractItemProvider implements FormDataProviderInt
             $staticItems = $fieldConfig['config']['items'];
 
             $fieldConfig['config']['items'] = $this->addItemsFromForeignTable($result, $fieldName, $fieldConfig['config']['items']);
-            $dynamicItems = array_diff_key($fieldConfig['config']['items'], $staticItems);
+            // removing items before $dynamicItems and $removedItems have been built results in having them
+            // not populated to the dynamic database row and displayed as "invalid value" in the forms view
+            $fieldConfig['config']['items'] = $this->removeItemsByUserStorageRestriction($result, $fieldName, $fieldConfig['config']['items']);
 
+            $dynamicItems = array_diff_key($fieldConfig['config']['items'], $staticItems);
             $removedItems = $fieldConfig['config']['items'];
 
             $fieldConfig['config']['items'] = $this->removeItemsByKeepItemsPageTsConfig($result, $fieldName, $fieldConfig['config']['items']);
index 224745e..a7e33ed 100644 (file)
@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Core\Resource\Service;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
@@ -32,17 +33,22 @@ class UserFileMountService
      * of a selected mount
      *
      * @param array $PA the array with additional configuration options.
-     * @return string The HTML code for the TCEform field
      */
     public function renderTceformsSelectDropdown(&$PA)
     {
+        $allowedStorageIds = array_map(
+            function(\TYPO3\CMS\Core\Resource\ResourceStorage $storage) {
+                return $storage->getUid();
+            },
+            $this->getBackendUserAuthentication()->getFileStorages()
+        );
         // If working for sys_filemounts table
         $storageUid = (int)$PA['row']['base'][0];
         if (!$storageUid) {
             // If working for sys_file_collection table
             $storageUid = (int)$PA['row']['storage'][0];
         }
-        if ($storageUid > 0) {
+        if ($storageUid > 0 && in_array($storageUid, $allowedStorageIds, true)) {
             /** @var $storageRepository \TYPO3\CMS\Core\Resource\StorageRepository */
             $storageRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\StorageRepository::class);
             /** @var $storage \TYPO3\CMS\Core\Resource\ResourceStorage */
@@ -123,4 +129,14 @@ class UserFileMountService
         }
         return $allFolderItems;
     }
+
+    /**
+     * Returns the BE USER Object
+     *
+     * @return BackendUserAuthentication
+     */
+    protected function getBackendUserAuthentication()
+    {
+        return $GLOBALS['BE_USER'];
+    }
 }