From b4965e06d2c073f24d57decff90e7cd8183e801e Mon Sep 17 00:00:00 2001 From: Helmut Hummel <helmut.hummel@typo3.org> Date: Tue, 10 Dec 2013 10:54:53 +0100 Subject: [PATCH] [SECURITY] Information Disclosure in Wizards 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 --- .../Controller/Wizard/FormsController.php | 33 +++++++++++++++++++ .../Controller/Wizard/RteController.php | 3 +- .../Controller/Wizard/TableController.php | 33 +++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/typo3/sysext/backend/Classes/Controller/Wizard/FormsController.php b/typo3/sysext/backend/Classes/Controller/Wizard/FormsController.php index aecad21dea2d..8c0c14b96513 100644 --- a/typo3/sysext/backend/Classes/Controller/Wizard/FormsController.php +++ b/typo3/sysext/backend/Classes/Controller/Wizard/FormsController.php @@ -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; + } } diff --git a/typo3/sysext/backend/Classes/Controller/Wizard/RteController.php b/typo3/sysext/backend/Classes/Controller/Wizard/RteController.php index 2bbfec246f25..8ffc9a254543 100644 --- a/typo3/sysext/backend/Classes/Controller/Wizard/RteController.php +++ b/typo3/sysext/backend/Classes/Controller/Wizard/RteController.php @@ -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); diff --git a/typo3/sysext/backend/Classes/Controller/Wizard/TableController.php b/typo3/sysext/backend/Classes/Controller/Wizard/TableController.php index 48b4ccd1e1b4..39f261531d2f 100644 --- a/typo3/sysext/backend/Classes/Controller/Wizard/TableController.php +++ b/typo3/sysext/backend/Classes/Controller/Wizard/TableController.php @@ -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; + } } -- GitLab