Fix open redirect

Make sure the "next" URL is in the same origin as Horizon before
redirecting to it.

Conflicts:
	horizon/test/unit/workflows/test_workflows.py

Adapted to work with Django before 1.11 which only has a host argument,
instead of allowed_hosts for django.utils.http.is_safe_url().

Change-Id: I06b2bfc8e3638591615547780c3fa34b0abe19f6
Closes-bug: #1865026
(cherry picked from commit 252467100f)
(cherry picked from commit baa370f843)
(cherry picked from commit 6c208edf32)
(cherry picked from commit 8825407c1b)
This commit is contained in:
Radomir Dopieralski 2020-09-07 21:03:36 +02:00 committed by Jan Zerebecki
parent 7fbe9ab5ce
commit cd4e6db77a
No known key found for this signature in database
GPG Key ID: 94D2D0D2432ED7CC
3 changed files with 42 additions and 3 deletions

View File

@ -14,8 +14,8 @@
from django import forms
from django import http
from django.test.utils import override_settings
import mock
import six
from horizon import exceptions
@ -359,3 +359,27 @@ class WorkflowsTests(test.TestCase):
flow = TestWorkflow(req, entry_point="test_action_two")
self.assertEqual("test_action_two", flow.get_entry_point())
@override_settings(ALLOWED_HOSTS=['localhost'])
def test_redirect_url_safe(self):
url = 'http://localhost/test'
view = TestWorkflowView()
request = self.factory.get("/", data={
'next': url,
})
request.META['SERVER_NAME'] = "localhost"
view.request = request
context = view.get_context_data()
self.assertEqual(url, context['REDIRECT_URL'])
@override_settings(ALLOWED_HOSTS=['localhost'])
def test_redirect_url_unsafe(self):
url = 'http://evilcorp/test'
view = TestWorkflowView()
request = self.factory.get("/", data={
'next': url,
})
request.META['SERVER_NAME'] = "localhost"
view.request = request
context = view.get_context_data()
self.assertIsNone(context['REDIRECT_URL'])

View File

@ -18,6 +18,7 @@ import json
from django import forms
from django import http
from django import shortcuts
from django.utils import http as utils_http
from django.views import generic
import six
@ -92,8 +93,15 @@ class WorkflowView(hz_views.ModalBackdropMixin, generic.TemplateView):
workflow = self.get_workflow()
workflow.verify_integrity()
context[self.context_object_name] = workflow
next = self.request.GET.get(workflow.redirect_param_name)
context['REDIRECT_URL'] = next
redirect_to = self.request.GET.get(workflow.redirect_param_name)
# Make sure the requested redirect is safe
if redirect_to and not utils_http.is_safe_url(
url=redirect_to,
host=self.request.get_host()):
redirect_to = None
context['REDIRECT_URL'] = redirect_to
context['layout'] = self.get_layout()
# For consistency with Workflow class
context['modal'] = 'modal' in context['layout']

View File

@ -0,0 +1,7 @@
---
security:
- |
An open redirect has been fixed, that could redirect users to arbitrary
addresses from certain views by specifying a "next" parameter in the URL.
Now the redirect will only work if the target URL is in the same domain,
and uses the same protocol.