Changes between Version 1 and Version 3 of Ticket #25905
- Timestamp:
- Dec 10, 2015, 4:48:09 PM (9 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Ticket #25905
- Property Component Core (Other) → File uploads/storage
- Property Triage Stage Unreviewed → Accepted
- Property Type Bug → Cleanup/optimization
-
Ticket #25905 – Description
v1 v3 1 It may be possible to override the hostname when displaying a link to a static/media file with an attacker-controlled filename. The url() method in FileStorageSystem uses urljoin(base,url) to combine the base_url (typically STATIC_URL or MEDIA_URL) to the filename. The urljoin function has an edge case where if the url parameter starts with "//", the base_url value is overwritten. Thus, if an attacker can set the name variable of a FileStorageSystem instance to "//www.evil.com", any url method call on that instance will return an external link pointing to the attacker's site. Creating a file of the name "\\www.evil.com"is also acceptable as the filepath_to_uri function (that is called on the filename before the urljoin call) converts all backslashes to forward-slashes. The latter example works better as it is a completely valid Linux file name.1 It may be possible to override the hostname when displaying a link to a static/media file with an attacker-controlled filename. The url() method in FileStorageSystem uses urljoin(base,url) to combine the base_url (typically STATIC_URL or MEDIA_URL) to the filename. The urljoin function has an edge case where if the url parameter starts with {{{"//"}}}, the base_url value is overwritten. Thus, if an attacker can set the name variable of a FileStorageSystem instance to {{{"//www.evil.com"}}}, any url method call on that instance will return an external link pointing to the attacker's site. Creating a file of the name {{{"\\www.evil.com"}}} is also acceptable as the filepath_to_uri function (that is called on the filename before the urljoin call) converts all backslashes to forward-slashes. The latter example works better as it is a completely valid Linux file name. 2 2 3 3 This issue can't be exploited using framework-provided upload techniques (FileFields, ImageFields, etc) as they properly escape the filename. However, an application may directly initialize a FileStorageSystem using user-controlled data or allow users to modify the name attribute of an existing FileStorageSystem instance. In such cases, an attacker could convert the expected relative paths into absolute external URLs. … … 5 5 This issue can simply be patched by modifying the line found here[https://github.com/django/django/blob/master/django/core/files/storage.py#L302] as follows: 6 6 7 return urljoin(self.base_url, filepath_to_uri(get_valid_filename(name)))7 {{{return urljoin(self.base_url, filepath_to_uri(name).replace('//','/'))}}} 8 8 9 9 This change filters the filename provided through the get_valid_filename function from django.utils.text. This function does a sufficient job of eliminating the ability to override the base_url.