[SECURITY] Information Disclosure in Wizards 21/26221/2
authorHelmut Hummel <helmut.hummel@typo3.org>
Tue, 10 Dec 2013 09:54:53 +0000 (10:54 +0100)
committerOliver Hader <oliver.hader@typo3.org>
Tue, 10 Dec 2013 09:54:57 +0000 (10:54 +0100)
It has been possible for authenticated editors
to show content of arbitrary tables and fields
that are defined in TCA by manipulating
GET parameters of the forms and table wizard.

This change adds a check if the editor has access
to the given record.

Change-Id: I8e27e5ffbccf148d951b50b21d9e15cc8e317442
Fixes: #41714
Releases: 4.5, 4.7, 6.0, 6.1, 6.2
Security-Commit: 52d4e3eced81639820db6d75f3d65d14c5234072
Security-Bulletin: TYPO3-CORE-SA-2013-004
Reviewed-on: https://review.typo3.org/26221
Reviewed-by: Oliver Hader
Tested-by: Oliver Hader
typo3/sysext/backend/Classes/Controller/Wizard/FormsController.php
typo3/sysext/backend/Classes/Controller/Wizard/RteController.php
typo3/sysext/backend/Classes/Controller/Wizard/TableController.php

index aecad21..8c0c14b 100644 (file)
@@ -277,6 +277,9 @@ class FormsController {
         * @todo Define visibility
         */
        public function formsWizard() {
+               if (!$this->checkEditAccess($this->P['table'], $this->P['uid'])) {
+                       throw new \RuntimeException('Wizard Error: No access', 1385807526);
+               }
                // First, check the references by selecting the record:
                $row = BackendUtility::getRecord($this->P['table'], $this->P['uid']);
                if (!is_array($row)) {
@@ -884,4 +887,34 @@ class FormsController {
                        </table>';
        }
 
+       /**
+        * Checks access for element
+        *
+        * @param string $table Table name
+        * @param integer $uid Record uid
+        * @return boolean
+        * @todo: Refactor to remove duplicate code (see TableController, RteController)
+        */
+       protected function checkEditAccess($table, $uid) {
+               $calcPRec = BackendUtility::getRecord($table, $uid);
+               BackendUtility::fixVersioningPid($table, $calcPRec);
+               if (is_array($calcPRec)) {
+                       // If pages:
+                       if ($table == 'pages') {
+                               $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms($calcPRec);
+                               $hasAccess = $CALC_PERMS & 2 ? TRUE : FALSE;
+                       } else {
+                               // Fetching pid-record first.
+                               $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms(BackendUtility::getRecord('pages', $calcPRec['pid']));
+                               $hasAccess = $CALC_PERMS & 16 ? TRUE : FALSE;
+                       }
+                       // Check internals regarding access:
+                       if ($hasAccess) {
+                               $hasAccess = $GLOBALS['BE_USER']->recordEditAccessInternals($table, $calcPRec);
+                       }
+               } else {
+                       $hasAccess = FALSE;
+               }
+               return $hasAccess;
+       }
 }
index 2bbfec2..8ffc9a2 100644 (file)
@@ -255,8 +255,9 @@ class RteController {
         *
         * @param string $table Table name
         * @param integer $uid Record uid
-        * @return void
+        * @return boolean
         * @todo Define visibility
+        * @todo: Refactor to remove duplicate code (see FormsController, TableController)
         */
        public function checkEditAccess($table, $uid) {
                $calcPRec = BackendUtility::getRecord($table, $uid);
index 48b4ccd..39f2615 100644 (file)
@@ -218,6 +218,9 @@ class TableController {
         * @todo Define visibility
         */
        public function tableWizard() {
+               if (!$this->checkEditAccess($this->P['table'], $this->P['uid'])) {
+                       throw new \RuntimeException('Wizard Error: No access', 1349692692);
+               }
                // First, check the references by selecting the record:
                $row = BackendUtility::getRecord($this->P['table'], $this->P['uid']);
                if (!is_array($row)) {
@@ -597,4 +600,34 @@ class TableController {
                return $cfgArr;
        }
 
+       /**
+        * Checks access for element
+        *
+        * @param string $table Table name
+        * @param integer $uid Record uid
+        * @return boolean
+        * @todo: Refactor to remove duplicate code (see FormsController, RteController)
+        */
+       protected function checkEditAccess($table, $uid) {
+               $calcPRec = BackendUtility::getRecord($table, $uid);
+               BackendUtility::fixVersioningPid($table, $calcPRec);
+               if (is_array($calcPRec)) {
+                       // If pages:
+                       if ($table == 'pages') {
+                               $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms($calcPRec);
+                               $hasAccess = $CALC_PERMS & 2 ? TRUE : FALSE;
+                       } else {
+                               // Fetching pid-record first.
+                               $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms(BackendUtility::getRecord('pages', $calcPRec['pid']));
+                               $hasAccess = $CALC_PERMS & 16 ? TRUE : FALSE;
+                       }
+                       // Check internals regarding access:
+                       if ($hasAccess) {
+                               $hasAccess = $GLOBALS['BE_USER']->recordEditAccessInternals($table, $calcPRec);
+                       }
+               } else {
+                       $hasAccess = FALSE;
+               }
+               return $hasAccess;
+       }
 }