This article describes the Django vulnerabilities CVE-2020-24583 and CVE-2020-24584, which were fixed on September 1, 2020.
See below for release information on the official website:
Django security releases issued: 3.1.1, 3.0.10 and 2.2.16 | Weblog | Django
Affected Versions
The following versions are affected.
- Django master branch
- Django 3.1
- Django 3.0
- Django 2.2
Vulnerability Description(Potential Account Hijack via Password Reset Form)
CVE-2020-24583: Incorrect permissions on intermediate-level directories on Python 3.7+
If you are using Python 3.7 or higher, and using FILE_UPLOAD_DIRECTORY_PERMISSIONS
, The FILE_UPLOAD_DIRECTORY_PERMISSIONS
was not applied to the following directories when executing the collectstatic
command:
- intermediate-level directories created in the process of uploading files
- intermediate-level collected static directories
Please note that upgrading Django will not change the permissions of the directory already created. You will have to change the permissions manually.
CVE-2020-24584: Permission escalation in intermediate-level directories of the file system cache on Python 3.7+
If you are using Python 3.7 or higher and you are using filesystem caching, the mid-level directory where the cache is placed was affected by the system standard umask value. Originally, 0o077 should be applied to the umask.
(i.e., permissions to “owned group” and “other” should always be zero.)
Proof of Concept
The version of the environment used in the sample code is as follows:
- Django 3.1
- Python 3.8.5
- Ubuntu 18.04.5
CVE-2020-24583: Incorrect permissions on intermediate-level directories on Python 3.7+
Add the following settings to settings.py
:
|
|
Check the permissions of the static
directory after the execution of collectstatic
.
|
|
If it is set to FILE_UPLOAD_DIRECTORY_PERMISSIONS
, it should be 0o700, but it is 0o777.
CVE-2020-24584: Permission escalation in intermediate-level directories of the file system cache on Python 3.7+
Add the following settings to settings.py
:
|
|
Execute umask 022
and then execute the following code with the shell
command:
|
|
Check the permissions of the created directory:
|
|
After deleting the foo
directory, run umask 000
and execute the following code (same as above) with the shell
command:
|
|
Check the permissions of the created directory:
|
|
You can see that the permissions of the created directories are affected by umask:
Which Code Was Wrong and How It Was Fixed
The actual changes can be found in the GitHub code below:
CVE-2020-24583:
- On the master branch
- On the 3.1 release branch
- On the 3.0 release branch
- On the 2.2 release branch
CVE-2020-24584:
- On the master branch
- On the 3.1 release branch
- On the 3.0 release branch
- On the 2.2 release branch
CVE-2020-24583 and CVE-2020-24584 are both due to a change in the os.makedirs
specification in Python 3.7 and above.
The following is the description of os.makedirs
from the official documentation:
Changed in version 3.7: The mode argument no longer affects the file permission bits of newly-created intermediate-level directories.
References: os — Miscellaneous operating system interfaces — Python 3.8.6 documentation
For validation, we have prepared the following code (requires Python 3.7 and above):
|
|
At first glance, it looks like the directory will always be created with permission 0o700, but the permissions on foo
, “ownership group” and “others” depend on the value of umask.
Running the above code after umask 022
will result in foo
having 0o755 permissions, while umast 000
will result in 0o777.
To work around this, Django now uses os.umask
before and after os.makedirs
with mode
in the code.
Here’s a modified example of the above code:
|
|