Skip to content

Commit 799cf35

Browse files
authored
[6.x] Harden auth redirects (#14093)
1 parent 51bf23b commit 799cf35

File tree

6 files changed

+59
-3
lines changed

6 files changed

+59
-3
lines changed

src/Http/Controllers/CP/Auth/PasskeyLoginController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Support\Facades\Auth;
77
use Statamic\Auth\WebAuthn\Serializer;
88
use Statamic\Contracts\Auth\User as UserContract;
9+
use Statamic\Facades\URL;
910
use Statamic\Facades\WebAuthn;
1011
use Statamic\Support\Str;
1112

@@ -43,6 +44,8 @@ private function successRedirectUrl()
4344
{
4445
$referer = request('referer');
4546

46-
return Str::contains($referer, '/'.config('statamic.cp.route')) ? $referer : cp_route('index');
47+
return Str::contains($referer, '/'.config('statamic.cp.route')) && ! URL::isExternalToApplication($referer)
48+
? $referer
49+
: cp_route('index');
4750
}
4851
}

src/Http/Controllers/TwoFactorChallengeController.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Inertia\Inertia;
99
use Statamic\Events\TwoFactorAuthenticationFailed;
1010
use Statamic\Events\ValidTwoFactorAuthenticationCodeProvided;
11+
use Statamic\Facades\URL;
1112
use Statamic\Http\Middleware\CP\HandleInertiaRequests;
1213
use Statamic\Http\Middleware\RedirectIfAuthenticated;
1314
use Statamic\Http\Requests\TwoFactorChallengeRequest;
@@ -67,6 +68,10 @@ protected function formAction()
6768

6869
protected function redirectPath()
6970
{
70-
return request('redirect') ?? route('statamic.site');
71+
$redirect = request('redirect');
72+
73+
return $redirect && ! URL::isExternalToApplication($redirect)
74+
? $redirect
75+
: route('statamic.site');
7176
}
7277
}

src/Http/Controllers/TwoFactorSetupController.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Illuminate\Http\Request;
66
use Inertia\Inertia;
7+
use Statamic\Facades\URL;
78
use Statamic\Facades\User;
89
use Statamic\Http\Middleware\CP\HandleInertiaRequests;
910

@@ -31,7 +32,11 @@ public function __invoke(Request $request)
3132

3233
protected function redirectPath()
3334
{
34-
return request('redirect') ?? route('statamic.site');
35+
$redirect = request('redirect');
36+
37+
return $redirect && ! URL::isExternalToApplication($redirect)
38+
? $redirect
39+
: route('statamic.site');
3540
}
3641

3742
protected function routes($user): array

tests/Feature/Auth/PasskeyLoginTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,21 @@ public function it_does_not_redirect_to_non_cp_referer()
122122
$this->assertAuthenticatedAs($user);
123123
}
124124

125+
#[Test]
126+
public function it_does_not_redirect_to_external_cp_referer()
127+
{
128+
$user = $this->createUser();
129+
WebAuthn::shouldReceive('getUserFromCredentials')->once()->andReturn($user);
130+
WebAuthn::shouldReceive('validateAssertion')->once()->andReturnTrue();
131+
132+
$this
133+
->loginRequest(['referer' => 'https://evil.com/cp/collections'])
134+
->assertOk()
135+
->assertJson(['redirect' => cp_route('index')]);
136+
137+
$this->assertAuthenticatedAs($user);
138+
}
139+
125140
#[Test]
126141
public function it_fails_when_validation_throws_exception()
127142
{

tests/Feature/Users/TwoFactorChallengeTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,23 @@ public function it_redirects_to_intended_url_after_successful_challenge()
191191
$this->assertAuthenticatedAs($user);
192192
}
193193

194+
#[Test]
195+
public function it_does_not_redirect_to_external_url_on_frontend_route()
196+
{
197+
$user = $this->userWithTwoFactorEnabled();
198+
199+
$this
200+
->session(['login.id' => $user->id()])
201+
->post(route('statamic.two-factor-challenge', [
202+
'redirect' => 'https://evil.com',
203+
]), [
204+
'code' => $this->getOneTimeCode($user),
205+
])
206+
->assertRedirect(route('statamic.site'));
207+
208+
$this->assertAuthenticatedAs($user);
209+
}
210+
194211
#[Test]
195212
public function the_session_is_elevated_upon_login()
196213
{

tests/Feature/Users/TwoFactorSetupTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ public function redirect_url_is_referer()
4545
->assertInertia(fn ($page) => $page->where('redirect', 'http://localhost/cp/collections'));
4646
}
4747

48+
#[Test]
49+
public function it_does_not_redirect_to_external_url_on_frontend_route()
50+
{
51+
$this
52+
->actingAs($this->userWithTwoFactorEnabled())
53+
->get(route('statamic.two-factor-setup', [
54+
'redirect' => 'https://evil.com',
55+
]))
56+
->assertRedirect(route('statamic.site'));
57+
}
58+
4859
private function user()
4960
{
5061
return tap(User::make()->makeSuper())->save();

0 commit comments

Comments
 (0)