$this->getTrustedHostsPatternStatus(), 'fileDenyPattern' => $this->getFileDenyPatternStatus(), 'htaccessUpload' => $this->getHtaccessUploadStatus(), 'exceptionHandler' => $this->getExceptionHandlerStatus(), 'exportedFiles' => $this->getExportedFilesStatus(), ]; if ($request !== null) { $statuses['encryptedConnectionStatus'] = $this->getEncryptedConnectionStatus($request); $lockSslStatus = $this->getLockSslStatus($request); if ($lockSslStatus) { $statuses['getLockSslStatus'] = $lockSslStatus; } } return $statuses; } public function getLabel(): string { return 'security'; } /** * Checks if the current connection is encrypted (HTTPS) */ protected function getEncryptedConnectionStatus(ServerRequestInterface $request): ReportStatus { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_ok'); $message = ''; $severity = ContextualFeedbackSeverity::OK; $normalizedParams = $request->getAttribute('normalizedParams'); if (!$normalizedParams->isHttps()) { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_insecure'); $severity = ContextualFeedbackSeverity::WARNING; $message = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_encryptedConnectionStatus_insecure'); } return new ReportStatus($this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_encryptedConnectionStatus'), $value, $message, $severity); } /** * @return ReportStatus */ protected function getLockSslStatus(ServerRequestInterface $request): ?ReportStatus { $normalizedParams = $request->getAttribute('normalizedParams'); if ($normalizedParams->isHttps()) { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_ok'); $message = ''; $severity = ContextualFeedbackSeverity::OK; if (!$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL']) { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_insecure'); $message = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_lockSslStatus_insecure'); $severity = ContextualFeedbackSeverity::WARNING; } return new ReportStatus($this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_lockSslStatus'), $value, $message, $severity); } return null; } /** * Checks if the trusted hosts pattern check is disabled. * * @return ReportStatus An object representing whether the check is disabled */ protected function getTrustedHostsPatternStatus(): ReportStatus { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_ok'); $message = ''; $severity = ContextualFeedbackSeverity::OK; if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] === VerifyHostHeader::ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL) { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_insecure'); $severity = ContextualFeedbackSeverity::ERROR; $message = $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.install_trustedhosts'); } return new ReportStatus($this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_trustedHostsPattern'), $value, $message, $severity); } /** * Checks if fileDenyPattern was changed which is dangerous on Apache * * @return ReportStatus An object representing whether the file deny pattern has changed */ protected function getFileDenyPatternStatus(): ReportStatus { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_ok'); $message = ''; $severity = ContextualFeedbackSeverity::OK; $fileAccessCheck = GeneralUtility::makeInstance(FileNameValidator::class); if ($fileAccessCheck->missingImportantPatterns()) { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_insecure'); $severity = ContextualFeedbackSeverity::ERROR; $message = sprintf( $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_deny_pattern_partsNotPresent'), '
' . htmlspecialchars($fileAccessCheck::DEFAULT_FILE_DENY_PATTERN) . '

' ); } return new ReportStatus($this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_fileDenyPattern'), $value, $message, $severity); } /** * Checks if fileDenyPattern allows to upload .htaccess files which is * dangerous on Apache. * * @return ReportStatus An object representing whether it's possible to upload .htaccess files */ protected function getHtaccessUploadStatus(): ReportStatus { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_ok'); $message = ''; $severity = ContextualFeedbackSeverity::OK; $fileNameAccess = GeneralUtility::makeInstance(FileNameValidator::class); if ($fileNameAccess->customFileDenyPatternConfigured() && $fileNameAccess->isValid('.htaccess')) { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_insecure'); $severity = ContextualFeedbackSeverity::ERROR; $message = $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_deny_htaccess'); } return new ReportStatus($this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_htaccessUploadProtection'), $value, $message, $severity); } protected function getExceptionHandlerStatus(): ReportStatus { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_ok'); $message = ''; $severity = ContextualFeedbackSeverity::OK; if ( str_contains($GLOBALS['TYPO3_CONF_VARS']['SYS']['productionExceptionHandler'], 'Debug') || (Environment::getContext()->isProduction() && (int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['displayErrors'] === 1) ) { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_insecure'); $severity = ContextualFeedbackSeverity::ERROR; $message = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_exceptionHandler_errorMessage'); } elseif ((int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['displayErrors'] === 1) { $severity = ContextualFeedbackSeverity::WARNING; $message = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_exceptionHandler_warningMessage'); } return new ReportStatus($this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_exceptionHandler'), $value, $message, $severity); } protected function getExportedFilesStatus(): ReportStatus { $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_ok'); $message = ''; $severity = ContextualFeedbackSeverity::OK; $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file'); $exportedFiles = $queryBuilder ->select('storage', 'identifier') ->from('sys_file') ->where( $queryBuilder->expr()->like( 'identifier', $queryBuilder->createNamedParameter('%/_temp_/importexport/%') ), $queryBuilder->expr()->or( $queryBuilder->expr()->like( 'identifier', $queryBuilder->createNamedParameter('%.xml') ), $queryBuilder->expr()->like( 'identifier', $queryBuilder->createNamedParameter('%.t3d') ) ), ) ->executeQuery() ->fetchAllAssociative(); if (count($exportedFiles) > 0) { $files = []; foreach ($exportedFiles as $exportedFile) { $files[] = '
  • ' . htmlspecialchars($exportedFile['storage'] . ':' . $exportedFile['identifier']) . '
  • '; } $value = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_insecure'); $severity = ContextualFeedbackSeverity::WARNING; $message = $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_exportedFiles_warningMessage'); $message .= ''; $message .= $this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_exportedFiles_warningRecommendation'); } return new ReportStatus($this->getLanguageService()->sL('LLL:EXT:reports/Resources/Private/Language/locallang_reports.xlf:status_exportedFiles'), $value, $message, $severity); } protected function getLanguageService(): LanguageService { return $GLOBALS['LANG']; } }