Skip to content

Commit

Permalink
fix: prevent open redirects on logout controller
Browse files Browse the repository at this point in the history
  • Loading branch information
imorland committed Jan 4, 2024
1 parent 45a8b57 commit bf95872
Showing 1 changed file with 39 additions and 4 deletions.
43 changes: 39 additions & 4 deletions framework/core/src/Forum/Controller/LogOutController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace Flarum\Forum\Controller;

use Flarum\Foundation\Config;
use Flarum\Http\Exception\TokenMismatchException;
use Flarum\Http\Rememberer;
use Flarum\Http\RequestUtil;
Expand Down Expand Up @@ -51,25 +52,33 @@ class LogOutController implements RequestHandlerInterface
*/
protected $url;

/**
* @var Config
*/
protected $config;

/**
* @param Dispatcher $events
* @param SessionAuthenticator $authenticator
* @param Rememberer $rememberer
* @param Factory $view
* @param UrlGenerator $url
* @param Config $config
*/
public function __construct(
Dispatcher $events,
SessionAuthenticator $authenticator,
Rememberer $rememberer,
Factory $view,
UrlGenerator $url
UrlGenerator $url,
Config $config
) {
$this->events = $events;
$this->authenticator = $authenticator;
$this->rememberer = $rememberer;
$this->view = $view;
$this->url = $url;
$this->config = $config;
}

/**
Expand All @@ -81,20 +90,21 @@ public function handle(Request $request): ResponseInterface
{
$session = $request->getAttribute('session');
$actor = RequestUtil::getActor($request);
$base = $this->url->to('forum')->base();

$url = Arr::get($request->getQueryParams(), 'return', $this->url->to('forum')->base());
$url = Arr::get($request->getQueryParams(), 'return', $base);

// If there is no user logged in, return to the index.
if ($actor->isGuest()) {
return new RedirectResponse($url);
return new RedirectResponse($base);
}

// If a valid CSRF token hasn't been provided, show a view which will
// allow the user to press a button to complete the log out process.
$csrfToken = $session->token();

if (Arr::get($request->getQueryParams(), 'token') !== $csrfToken) {
$return = Arr::get($request->getQueryParams(), 'return');
$return = $this->sanitizeReturnUrl($request->getQueryParams()['return'] ?? $base);

$view = $this->view->make('flarum.forum::log-out')
->with('url', $this->url->to('forum')->route('logout').'?token='.$csrfToken.($return ? '&return='.urlencode($return) : ''));
Expand All @@ -113,4 +123,29 @@ public function handle(Request $request): ResponseInterface

return $this->rememberer->forget($response);
}

protected function sanitizeReturnUrl(string $url): string
{
$parsed = parse_url($url);

if (! $parsed || ! isset($parsed['host'])) {
return '';
}

$host = $parsed['host'];

if (in_array($host, $this->getWhitelistedRedirectDomains())) {
return $url;
}

return '';
}

protected function getWhitelistedRedirectDomains(): array
{
return array_merge(
[$this->config->url()],
$this->config->offsetGet('trustedHosts') ?? []
);
}
}

0 comments on commit bf95872

Please sign in to comment.