Fix open redirect

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

Change-Id: I06b2bfc8e3638591615547780c3fa34b0abe19f6
Closes-bug: #1865026
This commit is contained in:
Radomir Dopieralski 2020-09-07 21:03:36 +02:00
parent b6b1d70d67
commit 252467100f
3 changed files with 42 additions and 2 deletions

View File

@ -16,6 +16,7 @@ from unittest import mock
from django import forms from django import forms
from django import http from django import http
from django.test.utils import override_settings
from horizon import base from horizon import base
from horizon import exceptions from horizon import exceptions
@ -399,3 +400,27 @@ class WorkflowsTests(test.TestCase):
flow = WorkflowForTesting(req, entry_point="action_two") flow = WorkflowForTesting(req, entry_point="action_two")
self.assertEqual("action_two", flow.get_entry_point()) self.assertEqual("action_two", flow.get_entry_point())
@override_settings(ALLOWED_HOSTS=['localhost'])
def test_redirect_url_safe(self):
url = 'http://localhost/test'
view = WorkflowViewForTesting()
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 = WorkflowViewForTesting()
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 forms
from django import http from django import http
from django import shortcuts from django import shortcuts
from django.utils import http as utils_http
from django.views import generic from django.views import generic
from horizon import exceptions from horizon import exceptions
@ -90,8 +91,15 @@ class WorkflowView(hz_views.ModalBackdropMixin, generic.TemplateView):
workflow = self.get_workflow() workflow = self.get_workflow()
workflow.verify_integrity() workflow.verify_integrity()
context[self.context_object_name] = workflow 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,
allowed_hosts=[self.request.get_host()]):
redirect_to = None
context['REDIRECT_URL'] = redirect_to
context['layout'] = self.get_layout() context['layout'] = self.get_layout()
# For consistency with Workflow class # For consistency with Workflow class
context['modal'] = 'modal' in context['layout'] 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.