From 8b036f2a3e457b0edb97cded94950eefc1c1b967 Mon Sep 17 00:00:00 2001 From: Nick Greenfield Date: Fri, 26 Sep 2014 11:08:58 -0700 Subject: [PATCH 1/2] Prevent open redirects when a malformed URL is passed to ?next= Example: "/login?next=http:///google.com" (note 3rd slash) --- flask_security/utils.py | 2 +- tests/test_common.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/flask_security/utils.py b/flask_security/utils.py index f75a17e..679ee61 100644 --- a/flask_security/utils.py +++ b/flask_security/utils.py @@ -212,7 +212,7 @@ def validate_redirect_url(url): return False url_next = urlsplit(url) url_base = urlsplit(request.host_url) - if url_next.netloc and url_next.netloc != url_base.netloc: + if url_next.scheme and url_next.netloc != url_base.netloc: return False return True diff --git a/tests/test_common.py b/tests/test_common.py index 7eeb298..b91c5e4 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -40,6 +40,12 @@ def test_authenticate_with_invalid_next(client, get_message): assert get_message('INVALID_REDIRECT') in response.data +def test_authenticate_with_invalid_malformed_next(client, get_message): + data = dict(email='matt@lp.com', password='password') + response = client.post('/login?next=http:///google.com', data=data) + assert get_message('INVALID_REDIRECT') in response.data + + def test_authenticate_case_insensitive_email(app, client): response = authenticate(client, 'MATT@lp.com', follow_redirects=True) assert b'Hello matt@lp.com' in response.data From 5bc37add88e7c6a4a024845306b043ab4c6f4628 Mon Sep 17 00:00:00 2001 From: Nick Greenfield Date: Wed, 1 Oct 2014 09:49:00 -0700 Subject: [PATCH 2/2] Update to use (url_next.netloc or url_next.scheme) in the validate_redirect_url open redirect patch. --- flask_security/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flask_security/utils.py b/flask_security/utils.py index 679ee61..ea3bffa 100644 --- a/flask_security/utils.py +++ b/flask_security/utils.py @@ -212,7 +212,7 @@ def validate_redirect_url(url): return False url_next = urlsplit(url) url_base = urlsplit(request.host_url) - if url_next.scheme and url_next.netloc != url_base.netloc: + if (url_next.netloc or url_next.scheme) and url_next.netloc != url_base.netloc: return False return True