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