[!!!][SECURITY] Allow first install only with FIRST_INSTALL file 12/28612/5
authorHelmut Hummel <helmut.hummel@typo3.org>
Thu, 27 Feb 2014 14:09:23 +0000 (15:09 +0100)
committerHelmut Hummel <helmut.hummel@typo3.org>
Fri, 21 Mar 2014 17:42:24 +0000 (18:42 +0100)
It was previously possible to access the install tool
by using a specially crafted URL, which caused
the install tool enable file check to fail.

As there was no easy solution to solve this issue,
we now introduce the need to create a file on first
install.

So in the installation directory the following must
be present:

d typo3
f index.php
f FIRST_INSTALL

After the installation the file will be removed.

Resolves: #55387
Releases: 6.2
Change-Id: I583581f18b939ba032950451bab17ac20131683b
Reviewed-on: https://review.typo3.org/28612
Reviewed-by: Markus Klein
Tested-by: Markus Klein
Reviewed-by: Helmut Hummel
Tested-by: Helmut Hummel
typo3/sysext/install/Classes/Controller/AbstractController.php
typo3/sysext/install/Classes/Controller/Action/Common/AccessNotAllowedAction.php [new file with mode: 0644]
typo3/sysext/install/Classes/Controller/Action/Step/EnvironmentAndFolders.php
typo3/sysext/install/Classes/Controller/AjaxController.php
typo3/sysext/install/Classes/Service/EnableFileService.php
typo3/sysext/install/Resources/Private/Templates/Action/Common/AccessNotAllowed.html [new file with mode: 0644]
typo3/sysext/install/Start/Install.php

index 61e4cb3..0153728 100644 (file)
@@ -27,6 +27,7 @@ namespace TYPO3\CMS\Install\Controller;
  ***************************************************************/
 
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Install\Service\EnableFileService;
 
 /**
  * Controller abstract for shared parts of Tool, Step and Ajax controller
@@ -49,6 +50,18 @@ class AbstractController {
        protected $authenticationActions = array();
 
        /**
+        * @return bool
+        */
+       protected function isInstallToolAvailable() {
+               /** @var \TYPO3\CMS\Install\Service\EnableFileService $installToolEnableService */
+               $installToolEnableService = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\EnableFileService');
+               if ($installToolEnableService->isFirstInstallAllowed()) {
+                       return TRUE;
+               }
+               return $installToolEnableService->checkInstallToolEnableFile();
+       }
+
+       /**
         * Guard method checking typo3conf/ENABLE_INSTALL_TOOL
         *
         * Checking ENABLE_INSTALL_TOOL validity is simple:
@@ -58,16 +71,18 @@ class AbstractController {
         * @return void
         */
        protected function outputInstallToolNotEnabledMessageIfNeeded() {
-               if (is_dir(PATH_typo3conf)) {
-                       /** @var \TYPO3\CMS\Install\Service\EnableFileService $installToolEnableService */
-                       $installToolEnableService = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\EnableFileService');
-                       if (!$installToolEnableService->checkInstallToolEnableFile()) {
+               if (!$this->isInstallToolAvailable()) {
+                       if (!EnableFileService::isFirstInstallAllowed() && !is_dir(PATH_typo3conf)) {
+                               /** @var \TYPO3\CMS\Install\Controller\Action\ActionInterface $action */
+                               $action = $this->objectManager->get('TYPO3\\CMS\\Install\\Controller\\Action\\Common\\AccessNotAllowedAction');
+                               $action->setAction('accessNotAllowed');
+                       } else {
                                /** @var \TYPO3\CMS\Install\Controller\Action\ActionInterface $action */
                                $action = $this->objectManager->get('TYPO3\\CMS\\Install\\Controller\\Action\\Common\\InstallToolDisabledAction');
-                               $action->setController('common');
                                $action->setAction('installToolDisabled');
-                               $this->output($action->handle());
                        }
+                       $action->setController('common');
+                       $this->output($action->handle());
                }
        }
 
diff --git a/typo3/sysext/install/Classes/Controller/Action/Common/AccessNotAllowedAction.php b/typo3/sysext/install/Classes/Controller/Action/Common/AccessNotAllowedAction.php
new file mode 100644 (file)
index 0000000..6287353
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+namespace TYPO3\CMS\Install\Controller\Action\Common;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Christian Kuhn <lolli@schwarzbu.ch>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Install\Controller\Action;
+
+/**
+ * Welcome page
+ */
+class AccessNotAllowedAction extends Action\AbstractAction {
+
+       /**
+        * Handle this action
+        *
+        * @return string content
+        */
+       public function executeAction() {
+               return $this->view->render();
+       }
+}
index ae86aa8..808a10f 100644 (file)
@@ -72,7 +72,9 @@ class EnvironmentAndFolders extends AbstractStepAction {
                        }
 
                        // Create enable install tool file after typo3conf & LocalConfiguration were created
+                       /** @var \TYPO3\CMS\Install\Service\EnableFileService $installToolService */
                        $installToolService = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\EnableFileService');
+                       $installToolService->removeFirstInstallFile();
                        $installToolService->createInstallToolEnableFile();
                }
 
index 1fd1374..74087fd 100644 (file)
@@ -65,7 +65,7 @@ class AjaxController extends AbstractController {
                $this->initializeObjectManager();
                // Warning: Order of these methods is security relevant and interferes with different access
                // conditions (new/existing installation). See the single method comments for details.
-               $this->checkInstallToolEnabled();
+               $this->outputInstallToolNotEnabledMessageIfNeeded();
                $this->checkInstallToolPasswordNotSet();
                $this->initializeSession();
                $this->checkSessionToken();
@@ -79,13 +79,9 @@ class AjaxController extends AbstractController {
         *
         * @return void
         */
-       protected function checkInstallToolEnabled() {
-               if (is_dir(PATH_typo3conf)) {
-                       /** @var \TYPO3\CMS\Install\Service\EnableFileService $installToolEnableService */
-                       $installToolEnableService = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\EnableFileService');
-                       if (!$installToolEnableService->checkInstallToolEnableFile()) {
-                               $this->output($this->unauthorized);
-                       }
+       protected function outputInstallToolNotEnabledMessageIfNeeded() {
+               if (!$this->isInstallToolAvailable()) {
+                       $this->output($this->unauthorized);
                }
        }
 
index 24b2343..74bd686 100644 (file)
@@ -38,6 +38,21 @@ class EnableFileService {
        const INSTALL_TOOL_ENABLE_FILE_PATH = 'typo3conf/ENABLE_INSTALL_TOOL';
 
        /**
+        * @constant Relative path to  FIRST_INSTALL file
+        */
+       const FIRST_INSTALL_FILE_PATH = 'FIRST_INSTALL';
+
+       /**
+        * @return bool
+        */
+       static public function isFirstInstallAllowed() {
+               if (!is_dir(PATH_typo3conf) && is_file(self::getFirstInstallFilePath())) {
+                       return TRUE;
+               }
+               return FALSE;
+       }
+
+       /**
         * Creates the INSTALL_TOOL_ENABLE file
         *
         * @return boolean
@@ -64,6 +79,15 @@ class EnableFileService {
        }
 
        /**
+        * Removes the FIRST_INSTALL file
+        *
+        * @return boolean
+        */
+       static public function removeFirstInstallFile() {
+               return unlink(self::getFirstInstallFilePath());
+       }
+
+       /**
         * Checks if the install tool file exists
         *
         * @return boolean
@@ -114,4 +138,13 @@ class EnableFileService {
        static protected function getInstallToolEnableFilePath() {
                return PATH_site . self::INSTALL_TOOL_ENABLE_FILE_PATH;
        }
+
+       /**
+        * Returns the path to the INSTALL_TOOL_ENABLE file
+        *
+        * @return string
+        */
+       static protected function getFirstInstallFilePath() {
+               return PATH_site . self::FIRST_INSTALL_FILE_PATH;
+       }
 }
diff --git a/typo3/sysext/install/Resources/Private/Templates/Action/Common/AccessNotAllowed.html b/typo3/sysext/install/Resources/Private/Templates/Action/Common/AccessNotAllowed.html
new file mode 100644 (file)
index 0000000..c5c1608
--- /dev/null
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+       <title>The Access to the Install Tool blocked</title>
+       <link rel="stylesheet" type="text/css" href="../Resources/Public/Stylesheets/Action/Common/EarlyExit.css?{time}" />
+</head>
+<body>
+<div id="container">
+       <h1>TYPO3</h1>
+       <div class="typo3-message message-warning">
+               <h2>Thank you for installing TYPO3</h2>
+               <p>
+                       To proceed with the installation, create the file <strong>FIRST_INSTALL</strong>
+                       in your root directory.
+                       The filename is case-sensitive but the file itself can be empty.
+               </p>
+
+               <p>
+                       <strong>Note:</strong>
+                       The file will be deleted once you proceed with the installation.
+               </p>
+       </div>
+</div>
+</body>
+</html>
index 1c52574..91f7f98 100644 (file)
@@ -118,17 +118,15 @@ require __DIR__ . '/../../core/Classes/Core/Bootstrap.php';
 
 // Execute 'tool' or 'step' controller depending on install[controller] GET/POST parameter
 $getPost = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('install');
-if (isset($getPost['controller']) && $getPost['controller'] === 'tool') {
-       $controller = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
-               'TYPO3\\CMS\\Install\\Controller\\ToolController'
-       );
-} elseif ($getPost['controller'] === 'ajax') {
-       $controller = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
-               'TYPO3\\CMS\\Install\\Controller\\AjaxController'
-       );
-} else {
-       $controller = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
-               'TYPO3\\CMS\\Install\\Controller\\StepController'
-       );
+$controllerClassName = 'TYPO3\\CMS\\Install\\Controller\\StepController';
+if (isset($getPost['controller'])) {
+       switch ($getPost['controller']) {
+               case 'tool':
+                       $controllerClassName = 'TYPO3\\CMS\\Install\\Controller\\ToolController';
+                       break;
+               case 'ajax':
+                       $controllerClassName = 'TYPO3\\CMS\\Install\\Controller\\AjaxController';
+                       break;
+       }
 }
-$controller->execute();
+\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($controllerClassName)->execute();