Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Further improve test cases.
Adds a test for the non-attack as a starting all-ok check.
Makes the absolute scheme://netloc request-uri case more lenient
as all we care about there is that the scheme://netloc makes it
into the Location: header in that scenario.
  • Loading branch information
gpshead committed Jun 16, 2022
commit 8563d4a74d7ee0abca7dc3910c9a2dac4e08ce65
19 changes: 14 additions & 5 deletions Lib/test/test_httpservers.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,11 +429,16 @@ def test_get_dir_redirect_location_domain_injection_bug(self):
"""
os.mkdir(os.path.join(self.tempdir, 'existing_directory'))
url = f'/python.org/..%2f..%2f..%2f..%2f..%2f../%0a%0d/../{self.tempdir_name}/existing_directory'
# Canonicalizes to /tmp/tempdir_name/existing_directory which does
# exist and is a dir, triggering the 301 redirect and former bug.
attack_url = f'/{url}' # //python.org... multi-slash prefix, no trailing slash
expected_location = f'{url}/' # /python.org.../ single slash single prefix, trailing slash
# Canonicalizes to /tmp/tempdir_name/existing_directory which does
# exist and is a dir, triggering the 301 redirect logic.
response = self.request(url)
self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
location = response.getheader('Location')
self.assertEqual(location, expected_location, msg='non-attack failed!')

# //python.org... multi-slash prefix, no trailing slash
attack_url = f'/{url}'
response = self.request(attack_url)
self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
location = response.getheader('Location')
Expand All @@ -442,7 +447,8 @@ def test_get_dir_redirect_location_domain_injection_bug(self):
msg='Expected Location header to start with a single / and '
Comment thread
gpshead marked this conversation as resolved.
'end with a / as this is a directory redirect.')
Comment thread
gpshead marked this conversation as resolved.

attack3_url = f'//{url}' # ///python.org... triple-slash prefix, no trailing slash
# ///python.org... triple-slash prefix, no trailing slash
attack3_url = f'//{url}'
response = self.request(attack3_url)
self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
self.assertEqual(response.getheader('Location'), expected_location)
Expand All @@ -456,7 +462,10 @@ def test_get_dir_redirect_location_domain_injection_bug(self):
response = self.request(attack_scheme_netloc_2slash_url)
self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
location = response.getheader('Location')
self.assertEqual(location, expected_scheme_netloc_location)
# We're just ensuring that the scheme and domain make it through, if
# there are or aren't multiple slashes at the start of the path that
# follows that isn't important in this Location: header.
self.assertTrue(location.startswith('https://pypi.org/'), msg=location)

def test_get(self):
#constructs the path relative to the root directory of the HTTPServer
Expand Down