1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

[1.6.x] Fixed #23157 -- Removed O(n) algorithm when uploading duplicate file names.

This is a security fix. Disclosure following shortly.
This commit is contained in:
Tim Graham
2014-08-08 10:20:08 -04:00
parent da051da8df
commit dd0c3f4ee1
8 changed files with 113 additions and 25 deletions

View File

@@ -83,5 +83,14 @@ the provided filename into account. The ``name`` argument passed to this method
will have already cleaned to a filename valid for the storage system, according
to the ``get_valid_name()`` method described above.
The code provided on ``Storage`` simply appends ``"_1"``, ``"_2"``, etc. to the
filename until it finds one that's available in the destination directory.
.. versionchanged:: 1.6.6
If a file with ``name`` already exists, an underscore plus a random 7
character alphanumeric string is appended to the filename before the
extension.
Previously, an underscore followed by a number (e.g. ``"_1"``, ``"_2"``,
etc.) was appended to the filename until an avaible name in the destination
directory was found. A malicious user could exploit this deterministic
algorithm to create a denial-of-service attack. This change was also made
in Django 1.5.9 and 1.4.14.

View File

@@ -81,6 +81,17 @@ The Storage Class
available for new content to be written to on the target storage
system.
.. versionchanged:: 1.6.6
If a file with ``name`` already exists, an underscore plus a random 7
character alphanumeric string is appended to the filename before the
extension.
Previously, an underscore followed by a number (e.g. ``"_1"``, ``"_2"``,
etc.) was appended to the filename until an avaible name in the
destination directory was found. A malicious user could exploit this
deterministic algorithm to create a denial-of-service attack. This
change was also made in Django 1.5.9 and 1.4.14.
.. method:: get_valid_name(name)

View File

@@ -18,3 +18,23 @@ To remedy this, URL reversing now ensures that no URL starts with two slashes
(//), replacing the second slash with its URL encoded counterpart (%2F). This
approach ensures that semantics stay the same, while making the URL relative to
the domain and not to the scheme.
File upload denial-of-service
=============================
Before this release, Django's file upload handing in its default configuration
may degrade to producing a huge number of ``os.stat()`` system calls when a
duplicate filename is uploaded. Since ``stat()`` may invoke IO, this may produce
a huge data-dependent slowdown that slowly worsens over time. The net result is
that given enough time, a user with the ability to upload files can cause poor
performance in the upload handler, eventually causing it to become very slow
simply by uploading 0-byte files. At this point, even a slow network connection
and few HTTP requests would be all that is necessary to make a site unavailable.
We've remedied the issue by changing the algorithm for generating file names
if a file with the uploaded name already exists.
:meth:`Storage.get_available_name()
<django.core.files.storage.Storage.get_available_name>` now appends an
underscore plus a random 7 character alphanumeric string (e.g. ``"_x3a1gho"``),
rather than iterating through an underscore followed by a number (e.g. ``"_1"``,
``"_2"``, etc.).

View File

@@ -18,3 +18,23 @@ To remedy this, URL reversing now ensures that no URL starts with two slashes
(//), replacing the second slash with its URL encoded counterpart (%2F). This
approach ensures that semantics stay the same, while making the URL relative to
the domain and not to the scheme.
File upload denial-of-service
=============================
Before this release, Django's file upload handing in its default configuration
may degrade to producing a huge number of ``os.stat()`` system calls when a
duplicate filename is uploaded. Since ``stat()`` may invoke IO, this may produce
a huge data-dependent slowdown that slowly worsens over time. The net result is
that given enough time, a user with the ability to upload files can cause poor
performance in the upload handler, eventually causing it to become very slow
simply by uploading 0-byte files. At this point, even a slow network connection
and few HTTP requests would be all that is necessary to make a site unavailable.
We've remedied the issue by changing the algorithm for generating file names
if a file with the uploaded name already exists.
:meth:`Storage.get_available_name()
<django.core.files.storage.Storage.get_available_name>` now appends an
underscore plus a random 7 character alphanumeric string (e.g. ``"_x3a1gho"``),
rather than iterating through an underscore followed by a number (e.g. ``"_1"``,
``"_2"``, etc.).

View File

@@ -19,6 +19,26 @@ To remedy this, URL reversing now ensures that no URL starts with two slashes
approach ensures that semantics stay the same, while making the URL relative to
the domain and not to the scheme.
File upload denial-of-service
=============================
Before this release, Django's file upload handing in its default configuration
may degrade to producing a huge number of ``os.stat()`` system calls when a
duplicate filename is uploaded. Since ``stat()`` may invoke IO, this may produce
a huge data-dependent slowdown that slowly worsens over time. The net result is
that given enough time, a user with the ability to upload files can cause poor
performance in the upload handler, eventually causing it to become very slow
simply by uploading 0-byte files. At this point, even a slow network connection
and few HTTP requests would be all that is necessary to make a site unavailable.
We've remedied the issue by changing the algorithm for generating file names
if a file with the uploaded name already exists.
:meth:`Storage.get_available_name()
<django.core.files.storage.Storage.get_available_name>` now appends an
underscore plus a random 7 character alphanumeric string (e.g. ``"_x3a1gho"``),
rather than iterating through an underscore followed by a number (e.g. ``"_1"``,
``"_2"``, etc.).
Bugfixes
========