mirror of
https://github.com/simonw/datasette.git
synced 2026-05-30 05:37:01 +02:00
Block open redirect via backslash in redirect Location
The leading-slash collapse added for #2429 only stripped forward slashes, so a path like /\example.com/ (or its %5C-encoded form) was redirected to Location: /\example.com. Browsers treat a backslash as a slash, so that resolves to //example.com and then https://example.com, re-opening the open redirect. Collapse leading backslashes as well as slashes. Extends the existing slash-slash test to cover /\example.com/ and /\/example.com/. Fixes #2680
This commit is contained in:
parent
d3330695fa
commit
9fbd31df00
2 changed files with 18 additions and 6 deletions
|
|
@ -330,9 +330,11 @@ async def asgi_send_html(send, html, status=200, headers=None):
|
|||
|
||||
|
||||
async def asgi_send_redirect(send, location, status=302):
|
||||
# Prevent open redirect vulnerability: strip multiple leading slashes
|
||||
# //example.com would be interpreted as a protocol-relative URL (e.g., https://example.com/)
|
||||
location = re.sub(r"^/+", "/", location)
|
||||
# Prevent open redirect vulnerability: collapse leading slashes and
|
||||
# backslashes into a single slash. Browsers treat a backslash as a slash,
|
||||
# so //example.com, /\example.com and /\/example.com would all otherwise be
|
||||
# interpreted as a protocol-relative URL (e.g. https://example.com/).
|
||||
location = re.sub(r"^[/\\]+", "/", location)
|
||||
await asgi_send(
|
||||
send,
|
||||
"",
|
||||
|
|
|
|||
|
|
@ -99,8 +99,18 @@ def test_custom_route_pattern_404(custom_pages_client):
|
|||
assert ">Oh no</" in response.text
|
||||
|
||||
|
||||
def test_custom_route_pattern_with_slash_slash_302(custom_pages_client):
|
||||
# https://github.com/simonw/datasette/issues/2429
|
||||
response = custom_pages_client.get("//example.com/")
|
||||
@pytest.mark.parametrize(
|
||||
"path",
|
||||
(
|
||||
# https://github.com/simonw/datasette/issues/2429
|
||||
"//example.com/",
|
||||
# https://github.com/simonw/datasette/issues/2680
|
||||
# Browsers treat backslashes as slashes, so these are also open redirects
|
||||
"/\\example.com/",
|
||||
"/\\/example.com/",
|
||||
),
|
||||
)
|
||||
def test_custom_route_pattern_open_redirect_302(custom_pages_client, path):
|
||||
response = custom_pages_client.get(path)
|
||||
assert response.status == 302
|
||||
assert response.headers["location"] == "/example.com"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue