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 http
from django.test.utils import override_settings
from horizon import base
from horizon import exceptions
@ -399,3 +400,27 @@ class WorkflowsTests(test.TestCase):
flow = WorkflowForTesting(req, entry_point="action_two")
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 http
from django import shortcuts
from django.utils import http as utils_http
from django.views import generic
from horizon import exceptions
@ -90,8 +91,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,
allowed_hosts=[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.