‪TYPO3CMS  10.4
SecurityStatus.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Http\Message\ServerRequestInterface;
31 use ‪TYPO3\CMS\Reports\Status as ReportStatus;
32 
37 {
41  protected ‪$request;
42 
49  public function ‪getStatus(ServerRequestInterface ‪$request = null)
50  {
51  $statuses = [
52  'trustedHostsPattern' => $this->‪getTrustedHostsPatternStatus(),
53  'adminUserAccount' => $this->‪getAdminAccountStatus(),
54  'fileDenyPattern' => $this->‪getFileDenyPatternStatus(),
55  'htaccessUpload' => $this->‪getHtaccessUploadStatus(),
56  'exceptionHandler' => $this->‪getExceptionHandlerStatus(),
57  'exportedFiles' => $this->‪getExportedFilesStatus(),
58  ];
59 
60  if (‪$request !== null) {
61  $statuses['encryptedConnectionStatus'] = $this->‪getEncryptedConnectionStatus(‪$request);
62  $lockSslStatus = $this->‪getLockSslStatus(‪$request);
63  if ($lockSslStatus) {
64  $statuses['getLockSslStatus'] = $lockSslStatus;
65  }
66  }
67 
68  return $statuses;
69  }
70 
77  protected function ‪getEncryptedConnectionStatus(ServerRequestInterface ‪$request): ReportStatus
78  {
79  $value = $this->‪getLanguageService()->‪getLL('status_ok');
80  $message = '';
81  $severity = ReportStatus::OK;
82 
84  $normalizedParams = ‪$request->getAttribute('normalizedParams');
85 
86  if (!$normalizedParams->isHttps()) {
87  $value = $this->‪getLanguageService()->‪getLL('status_insecure');
88  $severity = ReportStatus::WARNING;
89  $message = $this->‪getLanguageService()->‪sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_encryptedConnectionStatus_insecure');
90  }
91 
92  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_encryptedConnectionStatus'), $value, $message, $severity);
93  }
94 
99  protected function ‪getLockSslStatus(ServerRequestInterface ‪$request): ?ReportStatus
100  {
102  $normalizedParams = ‪$request->getAttribute('normalizedParams');
103 
104  if ($normalizedParams->isHttps()) {
105  $value = $this->‪getLanguageService()->‪getLL('status_ok');
106  $message = '';
107  $severity = ReportStatus::OK;
108 
109  if (!‪$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL']) {
110  $value = $this->‪getLanguageService()->‪getLL('status_insecure');
111  $message = $this->‪getLanguageService()->‪getLL('status_lockSslStatus_insecure');
112  $severity = ReportStatus::WARNING;
113  }
114 
115  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_lockSslStatus'), $value, $message, $severity);
116  }
117 
118  return null;
119  }
120 
126  protected function ‪getTrustedHostsPatternStatus(): ReportStatus
127  {
128  $value = $this->‪getLanguageService()->‪getLL('status_ok');
129  $message = '';
130  $severity = ReportStatus::OK;
131 
132  if (‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] === ‪GeneralUtility::ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL) {
133  $value = $this->‪getLanguageService()->‪getLL('status_insecure');
134  $severity = ReportStatus::ERROR;
135  $message = $this->‪getLanguageService()->‪sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.install_trustedhosts');
136  }
137 
138  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_trustedHostsPattern'), $value, $message, $severity);
139  }
140 
146  protected function ‪getAdminAccountStatus(): ReportStatus
147  {
148  $value = $this->‪getLanguageService()->‪getLL('status_ok');
149  $message = '';
150  $severity = ReportStatus::OK;
151 
152  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
153  $queryBuilder->getRestrictions()
154  ->removeAll()
155  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
156 
157  $row = $queryBuilder
158  ->select('uid', 'username', 'password')
159  ->from('be_users')
160  ->where(
161  $queryBuilder->expr()->eq(
162  'username',
163  $queryBuilder->createNamedParameter('admin', \PDO::PARAM_STR)
164  )
165  )
166  ->execute()
167  ->fetch();
168 
169  if (!empty($row)) {
170  try {
171  $hashInstance = GeneralUtility::makeInstance(PasswordHashFactory::class)->get($row['password'], 'BE');
172  if ($hashInstance->checkPassword('password', $row['password'])) {
173  // If the password for 'admin' user is 'password': bad idea!
174  // We're checking since the (very) old installer created instances like this in dark old times.
175  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
176  $value = $this->‪getLanguageService()->‪getLL('status_insecure');
177  $severity = ReportStatus::ERROR;
178  $editUserAccountUrl = (string)$uriBuilder->buildUriFromRoute(
179  'record_edit',
180  [
181  'edit[be_users][' . $row['uid'] . ']' => 'edit',
182  'returnUrl' => (string)$uriBuilder->buildUriFromRoute('system_reports')
183  ]
184  );
185  $message = sprintf(
186  $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.backend_admin'),
187  '<a href="' . htmlspecialchars($editUserAccountUrl) . '">',
188  '</a>'
189  );
190  }
191  } catch (‪InvalidPasswordHashException $e) {
192  // No hash class handling for current hash could be found. Not good, but ok in this case.
193  }
194  }
195 
196  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_adminUserAccount'), $value, $message, $severity);
197  }
198 
204  protected function ‪getFileDenyPatternStatus(): ReportStatus
205  {
206  $value = $this->‪getLanguageService()->‪getLL('status_ok');
207  $message = '';
208  $severity = ReportStatus::OK;
209 
210  $fileAccessCheck = GeneralUtility::makeInstance(FileNameValidator::class);
211  if ($fileAccessCheck->missingImportantPatterns()) {
212  $value = $this->‪getLanguageService()->‪getLL('status_insecure');
213  $severity = ReportStatus::ERROR;
214  $message = sprintf(
215  $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_deny_pattern_partsNotPresent'),
216  '<br /><pre>' . htmlspecialchars($fileAccessCheck::DEFAULT_FILE_DENY_PATTERN) . '</pre><br />'
217  );
218  }
219 
220  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_fileDenyPattern'), $value, $message, $severity);
221  }
222 
229  protected function ‪getHtaccessUploadStatus(): ReportStatus
230  {
231  $value = $this->‪getLanguageService()->‪getLL('status_ok');
232  $message = '';
233  $severity = ReportStatus::OK;
234 
235  $fileNameAccess = GeneralUtility::makeInstance(FileNameValidator::class);
236  if ($fileNameAccess->customFileDenyPatternConfigured()
237  && $fileNameAccess->isValid('.htaccess')) {
238  $value = $this->‪getLanguageService()->‪getLL('status_insecure');
239  $severity = ReportStatus::ERROR;
240  $message = $this->‪getLanguageService()->‪sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_deny_htaccess');
241  }
242 
243  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_htaccessUploadProtection'), $value, $message, $severity);
244  }
245 
246  protected function ‪getExceptionHandlerStatus(): ReportStatus
247  {
248  $value = $this->‪getLanguageService()->‪getLL('status_ok');
249  $message = '';
250  $severity = ReportStatus::OK;
251  if (
252  strpos(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['productionExceptionHandler'], 'Debug') !== false ||
253  (‪Environment::getContext()->isProduction() && (int)‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['displayErrors'] === 1)
254  ) {
255  $value = $this->‪getLanguageService()->‪getLL('status_insecure');
256  $severity = ReportStatus::ERROR;
257  $message = $this->‪getLanguageService()->‪getLL('status_exceptionHandler_errorMessage');
258  } elseif ((int)‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['displayErrors'] === 1) {
259  $severity = ReportStatus::WARNING;
260  $message = $this->‪getLanguageService()->‪getLL('status_exceptionHandler_warningMessage');
261  }
262  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_exceptionHandler'), $value, $message, $severity);
263  }
264 
265  protected function ‪getExportedFilesStatus(): ReportStatus
266  {
267  $value = $this->‪getLanguageService()->‪getLL('status_ok');
268  $message = '';
269  $severity = ReportStatus::OK;
270 
271  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file');
272  $exportedFiles = $queryBuilder
273  ->select('storage', 'identifier')
274  ->from('sys_file')
275  ->where(
276  $queryBuilder->expr()->like(
277  'identifier',
278  $queryBuilder->createNamedParameter('%/_temp_/importexport/%')
279  ),
280  $queryBuilder->expr()->orX(
281  $queryBuilder->expr()->like(
282  'identifier',
283  $queryBuilder->createNamedParameter('%.xml')
284  ),
285  $queryBuilder->expr()->like(
286  'identifier',
287  $queryBuilder->createNamedParameter('%.t3d')
288  )
289  )
290  )
291  ->execute()
292  ->fetchAll();
293 
294  if (count($exportedFiles) > 0) {
295  $files = [];
296  foreach ($exportedFiles as $exportedFile) {
297  $files[] = '<li>' . htmlspecialchars($exportedFile['storage'] . ':' . $exportedFile['identifier']) . '</li>';
298  }
299 
300  $value = $this->‪getLanguageService()->‪getLL('status_insecure');
301  $severity = ReportStatus::WARNING;
302  $message = $this->‪getLanguageService()->‪getLL('status_exportedFiles_warningMessage');
303  $message .= '<ul>' . implode(PHP_EOL, $files) . '</ul>';
304  $message .= $this->‪getLanguageService()->‪getLL('status_exportedFiles_warningRecommendation');
305  }
306 
307  return GeneralUtility::makeInstance(ReportStatus::class, $this->‪getLanguageService()->getLL('status_exportedFiles'), $value, $message, $severity);
308  }
309 
313  protected function ‪getLanguageService(): ‪LanguageService
314  {
315  return ‪$GLOBALS['LANG'];
316  }
317 }
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory
Definition: PasswordHashFactory.php:27
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus\$request
‪ServerRequestInterface $request
Definition: SecurityStatus.php:40
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus\getTrustedHostsPatternStatus
‪ReportStatus getTrustedHostsPatternStatus()
Definition: SecurityStatus.php:125
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus\getLockSslStatus
‪ReportStatus getLockSslStatus(ServerRequestInterface $request)
Definition: SecurityStatus.php:98
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus\getHtaccessUploadStatus
‪ReportStatus getHtaccessUploadStatus()
Definition: SecurityStatus.php:228
‪TYPO3\CMS\Core\Resource\Security\FileNameValidator
Definition: FileNameValidator.php:25
‪TYPO3\CMS\Core\Crypto\PasswordHashing\InvalidPasswordHashException
Definition: InvalidPasswordHashException.php:26
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus\getFileDenyPatternStatus
‪ReportStatus getFileDenyPatternStatus()
Definition: SecurityStatus.php:203
‪TYPO3\CMS\Reports\StatusProviderInterface\getStatus
‪array getStatus()
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus\getStatus
‪ReportStatus[] getStatus(ServerRequestInterface $request=null)
Definition: SecurityStatus.php:48
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:194
‪TYPO3\CMS\Core\Core\Environment\getContext
‪static ApplicationContext getContext()
Definition: Environment.php:133
‪TYPO3\CMS\Reports\Status
Definition: Status.php:24
‪TYPO3\CMS\Core\Utility\GeneralUtility\ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL
‪const ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL
Definition: GeneralUtility.php:47
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:38
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus\getLanguageService
‪LanguageService getLanguageService()
Definition: SecurityStatus.php:312
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus\getExceptionHandlerStatus
‪getExceptionHandlerStatus()
Definition: SecurityStatus.php:245
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus
Definition: SecurityStatus.php:37
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus\getExportedFilesStatus
‪getExportedFilesStatus()
Definition: SecurityStatus.php:264
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus\getEncryptedConnectionStatus
‪ReportStatus getEncryptedConnectionStatus(ServerRequestInterface $request)
Definition: SecurityStatus.php:76
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Reports\Report\Status\SecurityStatus\getAdminAccountStatus
‪ReportStatus getAdminAccountStatus()
Definition: SecurityStatus.php:145
‪TYPO3\CMS\Reports\Report\Status
Definition: ConfigurationStatus.php:16
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Reports\RequestAwareStatusProviderInterface
Definition: RequestAwareStatusProviderInterface.php:26
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Localization\LanguageService\getLL
‪string getLL($index)
Definition: LanguageService.php:154
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46