Skip to content

Commit 73b46b6

Browse files
bmackohader
authored andcommitted
[SECURITY] Avoid DoS when generating Error pages
TYPO3 now uses a lock strategy to avoid having to many request waiting for the generation of the error page (which cannot be generated via the external HTTP request, as there might be not enough workers / PHP processes available during a DoS attack). If a lock is in place, it directly returns a generic error response instead of waiting for the lock or that the error page is retrieved/rendered. Additionally, if the external error page could not be retrieved (HTTP status code other than 200), it will also create a generic response and cache that instead. This avoids keeping requesting for the errounous external HTTP page. This could happen when using external HTTP requests (Guzzle) to resolve an error page (via PageContentErrorHandler) for 404 sites. Resolves: #98384 Releases: 11.5, 10.4 Change-Id: Iae1cae882707a519b2cef85112525ea213a72eef Security-Bulletin: TYPO3-CORE-SA-2022-012 Security-References: CVE-2022-23500 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/77083 Tested-by: Oliver Hader <[email protected]> Reviewed-by: Oliver Hader <[email protected]>
1 parent 5e3e54d commit 73b46b6

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

typo3/sysext/core/Classes/Error/PageErrorHandler/PageContentErrorHandler.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@
2121
use Psr\Http\Message\ServerRequestInterface;
2222
use TYPO3\CMS\Core\Cache\CacheManager;
2323
use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException;
24+
use TYPO3\CMS\Core\Controller\ErrorPageController;
2425
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
2526
use TYPO3\CMS\Core\Http\HtmlResponse;
2627
use TYPO3\CMS\Core\Http\RequestFactory;
2728
use TYPO3\CMS\Core\LinkHandling\LinkService;
29+
use TYPO3\CMS\Core\Locking\Exception\LockAcquireWouldBlockException;
30+
use TYPO3\CMS\Core\Locking\LockFactory;
31+
use TYPO3\CMS\Core\Locking\LockingStrategyInterface;
2832
use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException;
2933
use TYPO3\CMS\Core\Site\Entity\Site;
3034
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
@@ -86,9 +90,25 @@ public function handlePageError(ServerRequestInterface $request, string $message
8690
$cacheContent = $cache->get($cacheIdentifier);
8791

8892
if (!$cacheContent && $resolvedUrl !== (string)$request->getUri()) {
93+
$lockFactory = GeneralUtility::makeInstance(LockFactory::class);
94+
$lock = $lockFactory->createLocker(
95+
$cacheIdentifier,
96+
LockingStrategyInterface::LOCK_CAPABILITY_EXCLUSIVE | LockingStrategyInterface::LOCK_CAPABILITY_NOBLOCK
97+
);
8998
try {
99+
$locked = $lock->acquire(
100+
LockingStrategyInterface::LOCK_CAPABILITY_EXCLUSIVE | LockingStrategyInterface::LOCK_CAPABILITY_NOBLOCK
101+
);
102+
if (!$locked) {
103+
return $this->createGenericErrorResponse();
104+
}
105+
90106
$subResponse = GeneralUtility::makeInstance(RequestFactory::class)
91107
->request($resolvedUrl, 'GET', $this->getSubRequestOptions());
108+
$lock->release();
109+
} catch (LockAcquireWouldBlockException $_) {
110+
$lock->release();
111+
return $this->createGenericErrorResponse();
92112
} catch (\Exception $e) {
93113
throw new \RuntimeException('Error handler could not fetch error page "' . $resolvedUrl . '", reason: ' . $e->getMessage(), 1544172838);
94114
}
@@ -124,6 +144,15 @@ public function handlePageError(ServerRequestInterface $request, string $message
124144
return new HtmlResponse($content, $this->statusCode);
125145
}
126146

147+
protected function createGenericErrorResponse(string $message = ''): ResponseInterface
148+
{
149+
$content = GeneralUtility::makeInstance(ErrorPageController::class)->errorAction(
150+
'Page Not Found',
151+
$message ?: 'The page did not exist or was inaccessible. Error page is being generated'
152+
);
153+
return new HtmlResponse($content, 503);
154+
}
155+
127156
/**
128157
* Returns request options for the subrequest and ensures, that a reasoneable timeout is present
129158
*
@@ -134,7 +163,7 @@ protected function getSubRequestOptions(): array
134163
$options = [];
135164
if ((int)$GLOBALS['TYPO3_CONF_VARS']['HTTP']['timeout'] === 0) {
136165
$options = [
137-
'timeout' => 30
166+
'timeout' => 10
138167
];
139168
}
140169
return $options;

0 commit comments

Comments
 (0)