Skip to content

Commit

Permalink
Prevent reflected file downloads on specially-named files
Browse files Browse the repository at this point in the history
This fixes #196, where it was observed that django_downloadview
was vulnerable to reflected file download attacks with
specially-named files, similar to CVE-2022-36359 in Django.
This change adopts the same replacement rules as used in Django's fix
in commit b3e4494d759202a3b6bf247fd34455bf13be5b80.
  • Loading branch information
tari committed Aug 1, 2024
1 parent e2b4470 commit 0568c3c
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
9 changes: 8 additions & 1 deletion django_downloadview/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,16 @@ def content_disposition(filename):
"""
if not filename:
return "attachment"
ascii_filename = encode_basename_ascii(filename)
# ASCII filenames are quoted and must ensure escape sequences
# in the filename won't break out of the quoted header value
# which can permit a reflected file download attack. The UTF-8
# version is immune because it's not quoted.
ascii_filename = (
encode_basename_ascii(filename).replace("\\", "\\\\").replace('"', r'\"')
)
utf8_filename = encode_basename_utf8(filename)
if ascii_filename == utf8_filename: # ASCII only.

return f'attachment; filename="{ascii_filename}"'
else:
return (
Expand Down
13 changes: 13 additions & 0 deletions tests/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,16 @@ def test_content_disposition_encoding(self):
self.assertIn(
"filename*=UTF-8''espac%C3%A9%20.txt", headers["Content-Disposition"]
)

def test_content_disposition_escaping(self):
"""Content-Disposition headers escape special characters."""
response = DownloadResponse(
"fake file",
attachment=True,
basename=r'"malicious\file.exe'
)
headers = response.default_headers
self.assertIn(
r'filename="\"malicious\\file.exe"',
headers["Content-Disposition"]
)

0 comments on commit 0568c3c

Please sign in to comment.