diff --git a/app/Http/Middleware/StartFireflySession.php b/app/Http/Middleware/StartFireflySession.php index eaf9b8ff9e..2f333ef4ac 100644 --- a/app/Http/Middleware/StartFireflySession.php +++ b/app/Http/Middleware/StartFireflySession.php @@ -42,16 +42,20 @@ class StartFireflySession extends StartSession */ protected function storeCurrentUrl(Request $request, $session): void { - $url = $request->fullUrl(); - $forbiddenWords = strpos($url, 'offline') || strpos($url, 'jscript') || strpos($url, 'delete') || strpos($url, '/login') || strpos($url, '/json') || strpos($url, 'serviceworker') || strpos($url, '/attachments/view'); + $url = $request->fullUrl(); + $safeUrl = app('steam')->getSafeUrl($url, route('index')); - if (false === $forbiddenWords - && 'GET' === $request->method() - && !$request->ajax()) { - //Log::debug(sprintf('Redirect is now "%s".', $url)); - $session->setPreviousUrl($url); + if ($url !== $safeUrl) { + //Log::debug(sprintf('storeCurrentUrl: converted "%s" to "%s", so will not use it.', $url, $safeUrl)); return; } - //Log::debug(sprintf('Refuse to set "%s" as current URL.', $url)); + + if ('GET' === $request->method() && !$request->ajax()) { + //Log::debug(sprintf('storeCurrentUrl: Redirect is now "%s".', $safeUrl)); + $session->setPreviousUrl($safeUrl); + + return; + } + //Log::debug(sprintf('storeCurrentUrl: Refuse to set "%s" as current URL.', $safeUrl)); } } diff --git a/app/Support/Steam.php b/app/Support/Steam.php index 5287febaee..cf911f9a15 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -31,7 +31,9 @@ use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use Illuminate\Support\Collection; use JsonException; +use Log; use stdClass; +use Str; /** * Class Steam. @@ -41,6 +43,53 @@ use stdClass; class Steam { + /** + * Returns the previous URL but refuses to send you to specific URLs. + * + * - outside domain + * - to JS files, API or JSON routes + * + * Uses the session's previousUrl() function as inspired by GitHub user @z1r0- + * + * session()->previousUrl() uses getSafeUrl() so we can safely return it: + * + * @return string + */ + public function getSafePreviousUrl(): string + { + //Log::debug(sprintf('getSafePreviousUrl: "%s"', session()->previousUrl())); + return session()->previousUrl() ?? route('index'); + } + + /** + * Make sure URL is safe. + * + * @param string $unknownUrl + * @param string $safeUrl + * + * @return string + */ + public function getSafeUrl(string $unknownUrl, string $safeUrl): string + { + //Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl)); + $returnUrl = $safeUrl; + $unknownHost = parse_url($unknownUrl, PHP_URL_HOST); + $safeHost = parse_url($safeUrl, PHP_URL_HOST); + + if (null !== $unknownHost && $unknownHost === $safeHost) { + $returnUrl = $unknownUrl; + } + + // URL must not lead to weird pages + $forbiddenWords = ['jscript', 'json', 'debug', 'serviceworker', 'offline', 'delete', '/login', '/attachments/view']; + if (Str::contains($returnUrl, $forbiddenWords)) { + $returnUrl = $safeUrl; + } + + return $returnUrl; + } + + /** * @param Account $account * @param Carbon $date