From a22fe9da829c8f9821fd5cf896f4d7316cec4917 Mon Sep 17 00:00:00 2001 From: meomap Date: Tue, 22 Nov 2016 12:36:00 +0700 Subject: [PATCH] don't allow signin view redirect to different host --- userena/tests/tests_views.py | 11 +++++++++++ userena/views.py | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/userena/tests/tests_views.py b/userena/tests/tests_views.py index 6860332a..9eb6e28d 100644 --- a/userena/tests/tests_views.py +++ b/userena/tests/tests_views.py @@ -314,6 +314,17 @@ def test_signin_view_success(self): 'next': '/accounts/'}) self.assertRedirects(response, '/accounts/') + def test_signin_view_with_unsafe_next(self): + """ + A ``POST`` to signin view with unsafe "next" parameter which + redirects to a different host, this should raise status forbidden + """ + response = self.client.post(reverse('userena_signin'), + data={'identification': 'john@example.com', + 'password': 'blowfish', + 'next': 'http://example.com'}) + self.assertEqual(response.status_code, 403) + def test_signin_view_with_invalid_next(self): """ If the value of "next" is not a real URL, this should not raise diff --git a/userena/views.py b/userena/views.py index a06d7214..d3acedb7 100644 --- a/userena/views.py +++ b/userena/views.py @@ -8,8 +8,9 @@ from django.views.generic.list import ListView from django.contrib import messages from django.core.exceptions import PermissionDenied +from django.utils.http import is_safe_url from django.utils.translation import ugettext as _ -from django.http import Http404, HttpResponseRedirect +from django.http import Http404, HttpResponseRedirect, HttpResponseForbidden from userena.forms import (SignupForm, SignupFormOnlyEmail, AuthenticationForm, ChangeEmailForm, EditProfileForm) @@ -457,6 +458,8 @@ def signin(request, auth_form=AuthenticationForm, redirect_to = redirect_signin_function( request.GET.get(redirect_field_name, request.POST.get(redirect_field_name)), user) + if not is_safe_url(url=redirect_to, host=request.get_host()): + return HttpResponseForbidden("Redirect to %r forbidden" % redirect_to) # noqa return HttpResponseRedirect(redirect_to) else: return redirect(reverse('userena_disabled',