Skip to content

Commit

Permalink
- Fix open redirect issue in redirect handling
Browse files Browse the repository at this point in the history
  • Loading branch information
dataflake committed Feb 23, 2021
1 parent c49ddb0 commit 7eead06
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Change Log
2.6.0 (unreleased)
------------------

- Fix open redirect issue in `Cookie Auth Helper` redirect handling

- Add support for Python 3.9.


Expand Down
8 changes: 8 additions & 0 deletions src/Products/PluggableAuthService/plugins/CookieAuthHelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import six
from six.moves.urllib.parse import quote
from six.moves.urllib.parse import unquote
from six.moves.urllib.parse import urlparse
from six.moves.urllib.parse import urlunparse

from AccessControl.class_init import InitializeClass
from AccessControl.Permissions import view
Expand Down Expand Up @@ -225,6 +227,12 @@ def unauthorized(self):
# in an endless redirect loop.
return 0

# Sanitize the return URL ``came_from`` and only allow local URLs
# to prevent an open exploitable redirect issue
if came_from:
parsed = urlparse(came_from)
came_from = urlunparse(('', '') + parsed[2:])

if '?' in url:
sep = '&'
else:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ def test_extractCredentials_with_deleted_cookie(self):
def test_challenge(self):
rc, root, folder, object = self._makeTree()
response = FauxCookieResponse()
testURL = 'http://test'
testPath = '/some/path'
testURL = 'http://test' + testPath
request = FauxRequest(RESPONSE=response, URL=testURL,
ACTUAL_URL=testURL)
root.REQUEST = request
Expand All @@ -138,7 +139,9 @@ def test_challenge(self):
helper.challenge(request, response)
self.assertEqual(response.status, 302)
self.assertEqual(len(response.headers), 3)
self.assertTrue(response.headers['Location'].endswith(quote(testURL)))
loc = response.headers['Location']
self.assertTrue(loc.endswith(quote(testPath)))
self.assertNotIn(testURL, loc)
self.assertEqual(response.headers['Cache-Control'], 'no-cache')
self.assertEqual(response.headers['Expires'],
'Sat, 01 Jan 2000 00:00:00 GMT')
Expand All @@ -159,8 +162,9 @@ def test_challenge_with_vhm(self):
self.assertEqual(response.status, 302)
self.assertEqual(len(response.headers), 3)
loc = response.headers['Location']
self.assertTrue(loc.endswith(quote(actualURL)))
self.assertTrue(loc.endswith(quote('/xxx')))
self.assertFalse(loc.endswith(quote(vhm)))
self.assertNotIn(actualURL, loc)
self.assertEqual(response.headers['Cache-Control'], 'no-cache')
self.assertEqual(response.headers['Expires'],
'Sat, 01 Jan 2000 00:00:00 GMT')
Expand Down

0 comments on commit 7eead06

Please # to comment.